日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

跟小静读CLR via C#(16)--泛型

發布時間:2024/4/13 C# 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 跟小静读CLR via C#(16)--泛型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

泛型就像是一個模板,常常定義一些通用的算法,具體調用時再替換成實際的數據類型,提高了代碼的可重用性。

一、初識泛型

1. 簡單實例

以最常用的FCL中的泛型List<T >為例:

static void Main(string[] args)
?????? {
?????????? List<int> num = new List<int>();
?????????? num.Add(1);
?????????? num.Add(3);
?????????? int num1 = num[0];
?????????? int num2 = num[1];
?????? }


尖括號中的T是不確定的數據類型,叫做類型參數,一般規定以字母T開頭,可以是TKey, TValue都可以。而調用時指定的具體類型叫做類型實參。

查看一下IL代碼:

  • 類型名List是以“`”加數字結尾的。數字表示類型的元數,也就是需要指定具體類型的參數個數。
  • 泛型是類型安全的。如果用“num.Add("a");”會發生編譯錯誤;
  • 泛型可以提高算法的可重用性,而且從例子中看出int類型并沒有進行裝箱拆箱操作,相比將所有類型轉換為Object的方式而言,提高了程序的性能。
  • 為泛型變量設置默認值時常使用default關鍵字進行,T temp=default(T)。如果T為引用類型,則temp為null;如果T為值類型,則temp設為0值.
2. 開放類型與封閉類型:

開放類型:具有泛型參數的類型是開放類型,如List<T>,CLR不允許構造開放類型的實例;

封閉類型:在實際調用代碼時,如果所有類型實參都已經指定了實際數據類型,如List<string>,則該類型為封閉類型。CLR允許構造封閉類型的實例。

3. 類型推斷:

先看這段很常見的代碼:

為了增強可讀性,編譯器支持類型推斷功能,省略<>,我們可以將上面調用的方法改為:

*?需要注意的是,類型推斷時C#使用的是變量的數據類型,而不是變量引用的對象的類型。例如:

雖然s1和s2都是指向了字符串對象,但是這兩個變量的類型是不同的,所以會產生編譯錯誤。

二、協變和逆變泛型類型參數

通過協變量和逆變量,可以將泛型委托或者接口的類型參數進行一定的類型轉換。

  • 逆變量:泛型類型參數可以從基類轉為派生類,用in關鍵字標識,只出現在輸入位置,例如方法的參數;

public delegate void Func<in T>(T arg);

static void Main(string[] args)

{

Func<object> f1 = null;

Func<string> f2 = f1;

}

  • 協變量:泛型類型參數可以從派生類改為它的基類,用out關鍵字標識,只出現在輸出位置,例如方法的返回值。

public delegate TResult Func<out TResult>();

static void Main(string[] args)

{

Func<string> fn=null;

object result=fn();

}

三、泛型約束

在設計泛型的類型參數時,可以通過where子句指定類型需要滿足的約束條件。主要包含以下幾種約束方式:

1. 主要約束

一個類型參數可以指定0或1個主要約束,主要約束可以一個非密封的引用類型,它表示類型實參必須與約束類型相同或者為約束類型的派生類。該引用類型不能為Object, Array, Delegate, MulticastDelegate, ValueType, Enum, Void。

class Constraint1<T> where T : Stream
{
???? public void Close(T stream)
???? {
???????? stream.Close();
???? }
}

class Program
{
???? static void Main(string[] args)
???? {
???????? Constraint1<FileStream> s2 = new Constraint1<FileStream>();
???? }
}

兩種特殊的主要約束:classstruct

  • Class約束:要求指定的類型實參必須是引用類型。Where T:class

在沒有約束的情況下,如果T為值類型,是不能賦值為null的,所以會產生編譯錯誤。添加約束后編譯通過:

  • Struct 約束:要求指定的類型實參必須是值類型

在沒有約束的情況下,如果T為引用類型是不能聲明為可空值類型的,所以會產生編譯錯誤。添加struct約束后運行正常:

2. 次要約束

一個類型參數可以指定0或者多個次要約束。常見的次要約束主要有兩種:

  • 接口約束:類型實參必須實現了指定的所有接口。例如:

接口約束的另外一個好處是:值類型實參調用接口方法時不用進行裝箱操作。

  • 類型參數約束:在指定的類型實參之間,存在著一定關系。例如要求存在繼承關系:

3. 構造器約束

構造器約束要求類型實參必須實現了無參構造器,而且它不支持有參構造器。





? ? 本文轉自 陳敬(Cathy) 博客園博客,原文鏈接:

http://www.cnblogs.com/janes/archive/2011/12/21/2295959.html

,如需轉載請自行聯系原作者



總結

以上是生活随笔為你收集整理的跟小静读CLR via C#(16)--泛型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。