2017-01-22 280 views
1

我對於什麼是對象轉換以及它的用途有點困惑。 我已閱讀關於Casting and type conversion的MSDN文檔,我可以看到爲了進行顯式轉換,您需要使用一個演員操作符。我理解文檔中給出的示例,如果在將一種類型轉換爲另一種類型時可能會丟失一些數據,則需要使用轉換運算符。什麼是對象鑄造?

我只是對如何投射物體感到困惑?我假設對象是一個類的實例,可能容納更多的信息,而不僅僅是一個簡單的數據類型?那麼,如何,爲什麼以及何時需要投射物體?

我見過鑄造一個對象,這是一個簡單的例子:

SomeType name = (SomeType)obj; 

我缺少的東西,或者是這個對象鑄造?如果是這樣,你需要在什麼情況下投出這樣的對象?

+0

拆箱是一種情況..我們不得不在c#中引入泛型方法之前進行過多的鑄造。這是因爲太多的方法使用'object'參數,比如非通用版本'List'。想想發件人如果輸入'object'並且你需要將它轉換爲'Button'的事件。確定'as'運營商是首選,但我只是想解釋一個有效的案例。 – user3185569

回答

2

您只需要使用鑄造操作員,當沒有隱式鑄造可用,編譯器可以驗證是安全的。如果有一個,編譯器確定演員會成功,那麼它會自動爲你做。

現在,爲什麼我應該使用演員?

  • A類型的對象,你需要B類型和 的對象是有辦法的A轉換成B:當您或者您應該使用一個演員。
  • 你有A類型的一個對象的引用,你需要一個 參考B類型到同一個對象,都AB是有效的引用類型到該對象。

另一種方式來思考是:

  • 當你知道的比編譯器更好,你知道一個對象是 類型編譯器不能。
  • 當一個對象不是某種類型,但你知道有一個有效的轉換爲該類型。

這帶來了一種分組蒙上基於什麼劇組真的是這樣做的:

  • 投保了保留身份。
  • 沒有的演員。

第一組是我們所說的參考轉換。它們根本不改變對象,它們只是改變指向對象的引用的類型(顯然,它們只適用於引用類型,值類型不能引用轉換,因爲你無法獲得對值的引用類型)。請注意,這種類型的轉換是由語言本身提供的,不能通過實現參考轉換。

第二組是所有需要在對象中發生表示變化的轉換,也就是說,由轉換返回的對象的位與被轉換對象的位不同。這些類型的類型是您可以在任何C#類/結構中實現的implicitexplicit運算符。

您可以閱讀更多關於此in this SO answer

好吧,這很有趣,但你能給我具體的例子嗎?是的,當然:

  1. 編譯器知道就夠了:

    interface IFoo { } 
    class Foo: Foo { } 
    IFoo foo = new Foo(); 
    

    有來自Foo隱式轉換到IFoo在最後聲明:IFoo foo = (Foo)(new Foo());。這個演員陣容將成功總是和編譯器知道有一個從FooIFoo隱式投射(參考轉換),所以它會爲你做。

  2. 我知道優於編譯器:

    object o = "Hello"; 
    var s = (string)o; 
    

    在這裏,我知道o真的是一個字符串,我告訴編譯器:即使你認爲o是一個對象,相信我,我知道它的一個字符串。

    這也是一個參考轉換。字符串Hello沒有以任何方式觸及,我們正在改變的唯一的事情就是指向它的參考。

  3. 我知道類型A的給定對象可轉換爲B類型的另一個對象,儘管不存在引用轉換。

    short s = 1; 
    int i = s; 
    

    注意,一個short不是int但恰好是一個方法(轉換運算符),其知道如何將short轉換爲int。這裏我們有一個從shortint的隱式轉換。 si有很不同的位,但有人實現了將短變成int的必要邏輯。

    現在請注意,這是一個隱式轉換,您不需要明確地轉換短暫的轉換,儘管沒有任何東西阻止您這樣做。它完全有效:int i = (int)s;

    double d = 1.5; 
    int i = (int)d; 
    

    在這裏,我們有相同類型的演員,但現在它明確。如果你會寫int i = d,你會得到一個編譯時錯誤,因爲這個轉換不是隱式的。

    這提出了一個有趣的觀點,你似乎在與演員混爲一談;信息丟失。隱式強制轉換不會丟失信息,但允許顯式強制轉換。這似乎是合理的,你不希望編譯器在沒有告訴你的情況下隱含地丟失信息;當您將short投射到int時,沒有風險,任何short都適合於int。當從double投射到int時,這顯然不是真實的,因此該投射被實施爲顯式。 (關於的注意事項實現了,這不是由語言強制執行的,它是編寫定義演員操作員的類的人的設計決定)。

0

只要您想使用該特定類型的對象,就會投射到特定對象。 投放到另一種類型的另一種方式是

SomeType x = obj as SomeType; 

在這裏,你不會得到一個異常時,obj爲null。雖然你應該檢查== null。

1

一個簡單有效的例子可以追溯到舊版本的C#。 List<T>沒有在該版本存在,爲了存儲數據的集合,你不得不使用非泛型集合:

static void Main(string[] args) 
{ 
    ArrayList list = new ArrayList(); 
    list.Add(1); 
    list.Add(2); 
    list.Add(3); 

    int total = 0; 
    foreach(object item in list) 
     total += (int)item; // without casting, compiler never knows item is int 

    Console.WriteLine("Total = {0}", total); 
} 

另一個有效的例子是事件,大多數事件使用的簽名(object sender, EventArgs e)。爲了訪問發件人,例如按鈕的元素,那麼你需要投:

Button btn = (Button)sender; 
Console.WriteLine(btn.Text); 

這是一個更好的做法是使用as運營商在正常鑄造防止空引用異常,但以上只是提供有效的例子。