国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

.NET泛型技巧之類型參數之間的轉換

2019-11-17 04:41:55
字體:
來源:轉載
供稿:網友

  首先我要介紹的技巧是如何提供類型參數之間的轉換。我們知道,.NET泛型將每個類型參數理解為一個獨立的類型。假如不通過約束指定,編譯器不會對類型參數所代表的類型做任何假設。也就是說,假如在某個上下文中有兩個不同的類型參數U和V,編譯器不會知道運行時他們代表的真實類型能否進行類型轉換,因此會拒絕編譯如下代碼:

Public Function GenericCast(Of U, V)(ByVal obj As U) As V
 Return CType(obj, V)
End Function
  除非我們加以約束U是V的子類。這顯然是為了類型安全做出的考慮,因為.NET這種跨程序集的泛型無法在編譯時做出足夠的檢查來確保類型安全。但是限制了這種操作,就妨礙了我們做事,很多代碼因此寫不出來。于是,我們可以利用.NET所有類型的基類Object來繞過這一限制:

Return DirectCast(DirectCast(obj, Object), V)
  VB的DirectCast運算符在泛型的類型參數上作用與C#的括號運算符相同。也就是說,這段代碼用C#寫起來是這樣:

return (V)(object)obj;
  這樣,即使不約束U和V之間的關系,這段代碼也能編譯了。但是他的功能卻不能令我們滿足。這樣寫出的類型轉換實際上還是僅當U是V本身或其子類的時候才能轉換成功。而其他一切情況都會轉換失敗。不管U和V的運行時類型之間是否定義有其他類型轉換規則。這顯然不合我們意愿,我們希望int與double之間的轉換等語言內置的類型轉換都能夠自動進行,否則就和約束沒什么兩樣了。對VB用戶來說有一個極為簡單的解決方案——把第二次DirectCast變成CType:

Public Function GenericCast(Of U, V)(ByVal obj As U) As V
 Return CType(DirectCast(obj, Object), V)
End Function
  現在,GenericCast泛型方法就能執行int與double等內置規則的轉換了。很神奇?因為CType運算符在編譯時自動調用了VB運行庫的轉換函數,該函數在運行期間對泛型類型參數的真實類型做了檢查。而且這個過程的性能完全可以接受。

  現在VB的用戶已經輕松享受這一功能了。但是C#的事情還沒完,因為C#沒有如此智能的類型轉換運算符,因此就需要手工實現VB運行庫所代辦的那些任務。其實就是利用了一下IConvertible:

static V GenericCast<U, V>(U obj)
{
 IConvertible convertibleObj = obj as IConvertible;
 if (convertibleObj != null)
 {
  Type t = typeof(V);

  switch (Type.GetTypeCode(t))
  {
   case TypeCode.Boolean:
    return (V)(object)convertibleObj.ToBoolean(null);
   case TypeCode.Byte:
    return (V)(object)convertibleObj.ToByte(null);
   case TypeCode.Char:
    return (V)(object)convertibleObj.ToChar(null);

   //.........
   default:
    //None of them, use the following default way..
    break;
  }
 }
 return (V)(object)obj;
}
  不過這個方法看起來不但很丑、很麻煩,功能上還達不到VB版。所以建議您用到這種類型參數之間的轉換,就用VB封裝這一功能,然后做成dll供C#調用吧。

  經過研究發現Convert.ChangeType方法已經封裝了IConvertible判定的那些代碼,因此C#版可采用這種寫法:

static V GenericCast<U, V>(U obj)
{
 return (V)Convert.ChangeType(obj, typeof(V));
}
  不過它仍然沒有VB版的CType功能豐富。此外我還發現了VB運行庫的ChangeType還有支持用戶自定義類型轉換運算符的功能。所以終極版本如下:

Public Function GenericCast(Of U, V)(ByVal obj As U) As V
Try
 Return CType(DirectCast(obj, Object), V)
 Catch ex As InvalidCastException Return DirectCast( _
  CompilerServices.Conversions.ChangeType(obj, GetType(V)), V)
 End Try
End Function

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 精河县| 蚌埠市| 永宁县| 贡觉县| 龙南县| 绥阳县| 阆中市| 扶绥县| 涿鹿县| 京山县| 威远县| 林芝县| 马龙县| 霍城县| 云浮市| 黄梅县| 嘉兴市| 容城县| 昂仁县| 郑州市| 平果县| 内江市| 遵义市| 阳泉市| 德化县| 临沧市| 阿克苏市| 伊春市| 名山县| 武胜县| 绵阳市| 榆林市| 大悟县| 徐水县| 河间市| 宣武区| 桂东县| 土默特左旗| 乐山市| 宜昌市| 平定县|