object to int c#




直接投射vs'as'運營商? (10)

考慮下面的代碼:

void Handler(object o, EventArgs e)
{
   // I swear o is a string
   string s = (string)o; // 1
   //-OR-
   string s = o as string; // 2
   // -OR-
   string s = o.ToString(); // 3
}

這三種類型的鑄造之間有什麼區別(好吧,第三種不是鑄造,但你有意圖)。 哪一個應該是首選?


  1. 當某件事一定是另一件事情時使用。
  2. 當某件事可能是另一件事時使用。
  3. 當你不關心它是什麼時使用,但你只是想使用可用的字符串表示。

“(string)o”將導致InvalidCastException,因為沒有直接轉換。

“o as string”將導致s為空引用,而不是拋出異常。

“o.ToString()”不是任何類型的類型轉換,它是一個由object實現的方法,因此以某種方式由.net中的每個類實現它被調用的類並返回一個字符串。

不要忘記,為了轉換為字符串,還有Convert.ToString(someType instanceOfThatType),其中someType是一組類型中的一種,本質上是框架的基本類型。


2對於轉換為派生類型非常有用。

假設a是動物:

b = a as Badger;
c = a as Cow;

if (b != null)
   b.EatSnails();
else if (c != null)
   c.EatGrass();

將獲得最少的投射。


使用直接投射string s = (string) o; 如果在你的應用程序的邏輯上下文中, string是唯一有效的類型。 採用這種方法,您將得到InvalidCastException並實現Fail-fast原則。 您的邏輯將被保護,以免進一步傳遞無效類型,或者在as運算符使用時得到NullReferenceException。

如果邏輯需要幾種不同的類型將string s = o as string; 並檢查它為null或使用is運營商。

C#7.0中出現了新的酷炫功能,可以簡化Cast和Check的模式匹配

if(o is string s)
{
  // Use string variable s
}

or

switch (o)
{
  case int i:
     // Use int variable i
     break;
  case string s:
     // Use string variable s
     break;
 }

如果你已經知道它可以施展什麼類型,使用C風格的演員:

var o = (string) iKnowThisIsAString; 

請注意,只有使用C風格轉換才能執行顯式類型強制轉換。

如果您不知道它是否是所需的類型,並且您要使用它,請使用as關鍵字:

var s = o as string;
if (s != null) return s.Replace("_","-");

//or for early return:
if (s==null) return;

請注意, 因為不會調用任何類型轉換操作符。 如果對像不是null並且是指定類型的本地對象,則它將僅為非null。

使用ToString()可以獲得任何對象的可讀的字符串表示,即使它不能轉換為字符串。


所有給出的答案都很好,如果我可以添加一些東西:要直接使用字符串的方法和屬性(例如ToLower),你不能寫:

(string)o.ToLower(); // won't compile

你只能寫:

((string)o).ToLower();

但你可以寫:

(o as string).ToLower();

as選項更具可讀性(至少對我來說)。


由於沒有人提到它,所以最接近實例的關鍵字是Java:

obj.GetType().IsInstanceOfType(otherObj)

當試圖獲得可能為空的任何(任何類型)的字符串表示時,我更喜歡下面的代碼行。 它緊湊,它調用ToString(),並且它正確地處理空值。 如果o為null,則s將包含String.Empty。

String s = String.Concat(o);

這實際上取決於你是否知道o是一個字符串,以及你想要做什麼。 如果你的評論意味著o真的是一個字符串,我寧願直接(string)o投射 - 它不可能失敗。

使用直接轉換的最大優點是,當它失敗時,會得到一個InvalidCastException ,它幾乎告訴你出了什麼問題。

使用as運算符,如果o不是字符串,則s設置為null ,如果您不確定並且想要測試s ,那麼這很方便:

string s = o as string;
if ( s == null )
{
    // well that's not good!
    gotoPlanB();
}

但是,如果您不執行該測試,則稍後將使用s並引發NullReferenceException 。 由於幾乎每條線都將一個變量解除引用並可能拋出一個變量,因此這些變量往往更常見,並且一旦發生在野外就很難追查到。 另一方面,如果你試圖轉換為值類型(任何原始類型或諸如DateTime結構),則必須使用直接投射 - 這as行不通的。

在轉換為字符串的特殊情況下,每個對像都有一個ToString ,所以如果o不為null,並且您認為ToString方法可以做到您想要的,則您的第三個方法可能沒問題。


string s = (string)o; // 1

如果o不是string則引發InvalidCastException 。 否則,即使onull ,也將o賦給s

string s = o as string; // 2

如果o不是string或者onull則將null賦給s 。 出於這個原因,你不能將它與值類型一起使用(在這種情況下,操作符永遠不能返回null )。 否則,將o賦給s

string s = o.ToString(); // 3

如果onull則會導致NullReferenceException 。 無論o是什麼類型,都將o.ToString()返回給s

使用1進行大多數轉換 - 這很簡單直接。 我傾向於幾乎從不使用2,因為如果事情不是正確的類型,我通常會期望發生異常。 我只看到需要使用錯誤代碼的糟糕設計庫(例如,返回null =錯誤,而不是使用例外)的返回null類型的功能。

3不是強制轉換,只是一個方法調用。 在需要非字符串對象的字符串表示時使用它。





casting