當我試圖通過擴展方法強制轉換對象時,出現了一個奇怪的問題。我有一個課程,我圍繞IPAddress
包裝了一些功能。在擴展方法中使用顯式強制轉換
// Dumbed down version of class
public sealed class PrefixLengthIPAddress
{
public static explicit operator IPAddress(PrefixLengthIPAddress address)
{
return (address != null) ? address._address : null;
}
public PrefixLengthIPAddress(IPAddress address)
{
_address = address;
_length = address.GetLength();
}
private readonly ushort _length;
private readonly IPAddress _address;
}
我不喜歡所有的括號的外觀提取IPAddress
出來的對象:
var family = ((IPAddress)prefixLengthAddress).AddressFamily;
我寧願能夠做這樣的事情:
var family = prefixLengthAddress.CastAs<IPAddress>().AddressFamily;
爲了做到這一點,我寫了以下擴展方法:
public static T CastAs<T>(this object value) where T : class
{
return (T)value;
}
與此
不幸的是我得到了InvalidCastException
:
var family = ((IPAddress)prefixLengthAddress).AddressFamily; // Works
var family = prefixLengthAddress.CastAs<IPAddress>().AddressFamily; // InvalidCastException
我明白,在這種特殊情況下,我可以簡單地揭露IPAddress
吸氣劑,但我們也有更復雜的顯式轉換,我想這樣做。
編輯
由於使用dynamic
克里斯·辛克萊的評論我已經更新了擴展方法是這樣的:
public static T CastAs<T>(this object value)
{
return (T)((dynamic)value);
}
有一些開銷使用dynamic
,但它比快更足以滿足我的需求。它似乎也適用於我嘗試過的所有基本類型轉換。
那麼'PrefixLengthIPAddress'在類型層次結構中與'IPAddress'沒有關係,這是問題的根本來源。你會使用這種鑄造代碼的其他情況是什麼?試圖任意強制將類型A的實例強制爲類型B的實例將會失敗。此外,通用實際上是無界的;所以'T'可以是一個'string',並且不會發生操作符重載。我懷疑爲'T'綁定'IPAddress'並不會導致你期望的行爲,即使這樣做了,否則你的擴展是無用的。 – Tejs 2013-04-03 21:34:03
我只是喜歡更好的擴展方法的外觀。如果我試圖將我的對象作爲字符串投射,我希望它以任何方式拋出InvalidCastException。 – lumberjack4 2013-04-03 21:48:58