2009-08-28 34 views
4

這工作:爲什麼參考參數不是逆變?

EndPoint endPoint = new IPEndPoint(_address, _port); 
_socket.ReceiveFrom(buffer, 0, 1024, SocketFlags.None, ref endPoint); 

但這並不:

IPEndPoint endPoint = new IPEndPoint(_address, _port); 
_socket.ReceiveFrom(buffer, 0, 1024, SocketFlags.None, ref endPoint); 

(注端點的類型)似乎很奇怪

。爲什麼ref關鍵字破壞參數逆變?

+2

更好的問題是「爲什麼輸出參數不是協變的?」 Out參數在幕後實現與ref參數完全相同;我們所做的只是改變編譯器執行的明確分配規則。由於參數參數既可以讀取也可以寫入,所傳遞變量的類型不能改變任一方向;因爲out參數只是花式參考參數,所以它們也不能改變。 – 2009-08-28 15:17:08

+0

謝謝埃裏克,這很有道理。 Ref是一個有趣的,它似乎在C#的'乾淨'實施,我們不應該真的需要它... – 2009-08-31 19:53:25

回答

17

因爲在方法簽名中,endPoint參數被聲明爲EndPoint,而不是IPEndPoint;不能保證該方法不會將endPoint設置爲另一種類型的EndPoint,而該EndPoint將不會被分配給IPEndPoint變量。

例如,假設你有一個FooEndPoint類,從EndPoint繼承和Foo方法,它接受ref EndPoint參數:

public class FooEndPoint : EndPoint 
{ 
    ... 
} 

public void Foo(ref EndPoint endPoint) 
{ 
    ... 
    endPoint = new FooEndPoint(); 
    ... 
} 

如果你能夠在IPEndPoint傳遞給方法,的分配新建分配FY一個FooEndPointendPoint參數會在運行時失敗,因爲FooEndPoint不是IPEndPoint

+0

我明白你的迴應背後的邏輯,爲什麼他們可以決定對此做出規則,但我相信我他同意這張海報,因爲他首先提出的問題是這是一個不正確的規則。編譯器至多應該提供一個警告,說明可能會發生不正確的運行時分配。但是應該由開發人員來處理某種類型的不正確的異常,而不是不被允許。 – 2009-10-06 14:19:43

+0

這是用4.0中的dynamic關鍵字解決的問題之一嗎? – 2009-10-06 14:20:24

+1

如需更詳細的解釋,請查看Eric Lippert的這篇文章:http://blogs.msdn.com/ericlippert/archive/2009/09/21/why-do-ref-and-out-parameters-not-allow型,variation.aspx – 2009-10-06 15:39:56

2

因爲該方法ReceiveFrom可以創建一個新的端點 - 但不是IPEndPoint。該參數有兩種工作方式,因此類型需要完全匹配。