c# - winform - 即使沒有空檢查,使用“as”而不是cast是否有意義?




winform alert dialog (9)

人們喜歡這麼多,因為它讓他們感到安全,不受例外的影響......就像在盒子上保證一樣。 一個人在盒子上提供了一個奇特的保證,因為他希望你能感受到裡面的溫暖和溫暖。 你認為你在晚上把那個小盒子放在你的枕頭下面,保證仙子可能會下來並留下四分之一,我是不是Ted?

回到主題......使用直接投射時, 可能會出現無效投射異常。 因此,人們將as作為一攬子解決方案應用於他們所有的演員需求,因為(本身)永遠不會拋出異常。 但是有趣的是,在你給出的例子(x as T).SomeMethod(); 您正在為空引用異常交易無效的轉換異常。 當你看到異常時,會模糊真正的問題。

我通常不會使用太多。 我更喜歡is測試,因為對我來說,它看起來更具可讀性,並且更有意義,然後嘗試進行強制轉換並檢查null。

在開發博客,在線代碼示例和(最近)甚至是一本書中,我一直在這樣的代碼中徘徊:

var y = x as T;
y.SomeMethod();

或者更糟糕的是:

(x as T).SomeMethod();

這對我來說沒有意義。 如果你確定xT類型,你應該使用直接轉換: (T)x 。 如果您不確定,可以使用as但在執行某些操作之前需要檢查null 。 上述代碼所做的一切就是將一個(有用的) InvalidCastException變成一個(無用的) NullReferenceException

我是唯一一個認為這是公然濫用as關鍵字的人嗎? 或者我錯過了一些顯而易見的事實,而上述模式實際上有意義?


你的理解是真實的。 這聽起來像試圖微觀優化我。 當你確定類型時,你應該使用正常的強制轉換。 除了產生更明智的例外,它也快速失敗。 如果您對該類型的假設錯誤,那麼您的程序將立即失敗,您將能夠立即查看失敗的原因,而不是等待NullReferenceExceptionArgumentNullException或者將來某個時候出現邏輯錯誤。 一般來說,一個沒有在任何地方進行null檢查的表達式是一種代碼異味。

另一方面,如果您對演員陣容不確定,並期望演員陣容失敗,則應該使用包含try-catch塊的普通演員陣容。 此外,推薦使用as類型檢查,然後是cast。 代替:

if (x is SomeType)
   ((SomeType)x).SomeMethod();

它會為is關鍵字生成isinst指令 ,並為castclass生成isinst指令 (有效地執行兩次),您應該使用:

var v = x as SomeType;
if (v != null)
    v.SomeMethod();

這只會生成一個isinst指令。 前一種方法在多線程應用程序中可能存在缺陷,因為競爭條件可能會導致變量在is檢查成功並在鑄造線失敗後更改其類型。 後一種方法不容易出現這種錯誤。

建議不要在生產代碼中使用以下解決方案。 如果你真的討厭C#中這樣一個基本的構造,你可能會考慮切換到VB或其他語言。

如果一個人拼命憎恨演員的語法,他/她可以寫一個擴展方法來模仿演員:

public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ...
    return (T)o;
}

並使用一個整潔的[?]語法:

obj.To<SomeType>().SomeMethod()

使用'as'不適用於用戶定義的轉換,而演員將在適當的時候使用它們。 在某些情況下,這可能是一個重要的區別。


只是因為人們喜歡它的外觀,它的可讀性很強。

讓我們面對它吧:類C語言中的轉換/轉換操作符非常可怕,可讀性強。 如果C#採用了以下的Javascript語法,我希望它更好:

object o = 1;
int i = int(o);

或者定義一個to操作符,該等效的操作等同as

object o = 1;
int i = o to int;

我在這裡寫了一些關於這個的內容:

blogs.msdn.com/ericlippert/archive/2009/10/08/…

我明白你的觀點。 我同意它的主旨:一個演員操作員溝通“我確信這個對象可以轉換為該類型,並且如果我錯了,我願意冒一個例外的風險”,而一個“as”操作符通信“我不確定這個對象可以轉換為這種類型,如果我錯了,給我一個null。”

但是,有一個細微的差別。 (x as T).Whatever()表示“我知道不只是x可以轉換為T,而且,這樣做只涉及引用或拆箱轉換,並且此外x不為空”。 這確實傳遞了不同於((T)x)的信息.Whatever(),也許這就是代碼作者的意圖。


我相信as關鍵字可以被認為是來自C ++的更加優雅的dynamic_cast版本。


沒有技術原因,它可能更受歡迎,只是因為它更易於閱讀並且更直觀。 (並不是說它只是試圖回答這個問題而已)


當我使用“as”時,99%的時間是當我不確定實際對像類型是什麼時

var x = obj as T;
if(x != null){
 //x was type T!
}

我不想捕捉明確的投射異常,也不想投兩次,使用“is”:

//I don't like this
if(obj is T){
  var x = (T)obj; 
}

這必須是我最崇拜的人之一

Stroustrup的D&E和/或我現在找不到的一些博客帖子討論了to運算符的概念,它將解決https://.com/users/73070/johannes-rossel (即與與DirectCast語義)。

這沒有得到實施的原因是因為演員陣容應該導致痛苦並且變得醜陋,所以你被推開使用它。

可惜的是,'聰明的'程序員(通常是書籍作者(Juval Lowy IIRC))通過濫用這種方式來解決這個問題(C ++並沒有提供,可能是出於這個原因)。

甚至VB在統一語法方面也有更多的一致性,強制你選擇TryCastDirectCast下定決心





type-conversion