首頁 >後端開發 >C#.Net教程 >C# 泛型的約束圖文詳細介紹

C# 泛型的約束圖文詳細介紹

黄舟
黄舟原創
2017-03-07 10:59:151606瀏覽

本文將詳細介紹C# 泛型的限制:引用型別約束;值型別約束;建構子型別約束;轉換型別約束;組合約束的相關知識。具有很好的參考價值,下面跟著小編一起來看下吧

1.引用型別約束

struct RefSample8742468051c85b06f0a0af9e3e506b5c where T:class         引用型別Class表示約束,其他的引用型別為特定的限制。

表示對於的約束必須為一個類別(引用類型)不能是值類型(int,char,datatime,struct),可以是介面interface

區分,陣列為引用類型,因為定義數組時需要new出一個物件。

雖然定義成RefSample8742468051c85b06f0a0af9e3e506b5c 傳入的必須為引用類型但是RefSample仍然為值類型

2.值類型限制

#class ValSample8742468051c85b06f0a0af9e3e506b5c where T:struct

#為引用類型,因為int,char等型別都是struct

#ValSamplebd43222e33876353aff11e13a7dc75f6

3.建構子類型限制

public T CreateInstance<T>() where T:new()
{
  return new T();
}

指定的類型T必須有建構函數,CreateInstancebd43222e33876353aff11e13a7dc75f6和CreateInstance273238ce9338fbb04bee6997e5552b95 都是有效的。但是CreateInstance8ac337f12ac35ec97e8dd89560472ecc沒有建構子。

4.轉換類型約束

一種約束允許你指定另一個類型,型別實參必須可以透過一致性、引用或裝箱轉換隱含地轉換為該類型。你也可以規定一個型別實參必須可以轉換為另一個型別實參-這稱為型別參數約束。

理解的意思:可以互換,就是我們可以透過裝箱或強制型別轉換成目標型別的 型別都可以用於型別參數傳入。

class Sample8742468051c85b06f0a0af9e3e506b5c where T:Stream

有效:Sample7deb1b66c2439bfe6895a394cbb2197a 這本身符合約束

#無效:Samplef7e83be87db5cd2d9a8a0b8117b38cd4 因為String類型無法透過引用或是裝箱拆箱強制轉換成Stream、

struct Sample8742468051c85b06f0a0af9e3e506b5c where T:IDisposable

#規定T必須為IDisposable 類型的參考類型

有效:Sampleee3398fcc71686d89f0818db05b7a88f引用轉換

無效:Sample66631937a557270cbf0605de1ac49062

#分析:為什麼SqlConnection 可以而StringBuilder不可以?它們都是引用型別

1.SqlConnection實作了IDisposable接口,所以可以協變

##2.StringBuilder只實作了ISerializable接口,無法透過途徑轉換為IDisposable

class Sample8742468051c85b06f0a0af9e3e506b5c where T:IComparable8742468051c85b06f0a0af9e3e506b5c##因為IComparable8742468051c85b06f0a0af9e3e506b5c整體當作約束,分析IComparable< ;T>的類型,可以用Type.IsValueType判斷,true為值型,false為引用型別

typeof(IComparable8742468051c85b06f0a0af9e3e506b5c).IsValueType   結果為false表示為引用類型有效:Samplebd43222e33876353aff11e13a7dc75f6(裝箱轉換)

無效:Sampled0869186ef29f1614dd65eb5411320d5

也可以指定多種限制:

class sample8742468051c85b06f0a0af9e3e506b5c where T:stream,IEnumerable98c455a79ddfebb79781bff588e7b37e,IComparablebd43222e33876353aff11e13a7dc75f6

#class Samplea3a33c0ecb70a91b4d9230494d6d6b18 where T:U有效:Sample8ef407ed57caac12483dcecdcac4eb46

無效:Sample6f72722a2a297c03396b6f57d1a9f381

#總結:要看傳入類別參數是否可以轉換,查看規定參數和傳入類別參數是否實現同一接口,如果實作則可以,否則不可以。

不可以是以下:System.Object,System.Enum,System.ValueType,System.Delegate,結構或密封類別(String)

5.組合約束

對型別參數的限制有多個,注意:只能是一種型,值型別和參考型別不能同時存在,沒用一個型別就是引用型別,又是值型別。

由於每個值類型都有一個無建構函數,此後不能再有建構子約束

有效:

class Sample8742468051c85b06f0a0af9e3e506b5c where T:class,IDisposable,new( )
class Samplea62d1d8805a91a8900e4e7c7c3ba59db where T:Stream where U:IDispsable

無效:

class Sample8742468051c85b06f0a0af9e3e506b5c where T:class,struct (沒有任何類型即時引用類型又是值類型的,所以為無效的)

class Sample8742468051c85b06f0a0af9e3e506b5c where T:Stream,class (引用型別約束應該是第一個約束,放在最前面,所以為無效的) Stream只是約束傳入參數為Stream具體類型,而class約束為引用類型,一開始我理解錯了
class Sample8742468051c85b06f0a0af9e3e506b5c where T:new() ,Stream   (new() 必須放在最後)

class Sample8742468051c85b06f0a0af9e3e506b5c where T:IDisposable,Stream (類別必須放在介面前面,所以為無效的)

class Sample8742468051c85b06f0a0af9e3e506b5c where T:XmlReader,IComparable,IComparable (對於轉換類型約束,同一個介面不能出現多次

class Sample< ;T,U> where T:struct where  U:Class,T (類型形參「T」有「struct」約束,因此「T」不能用作「U」的約束,所以為無效的)

class Samplec619abd6b5b072b4427165f6c9e6f6e4 where T:Stream ,U:IDisposable  語法錯誤

看到網路上還有這種版本也是有效的我表示不理解:

class Sample8742468051c85b06f0a0af9e3e506b5c where T:struct,IDisapsable  IDisapsable為值類型?

class Samplea62d1d8805a91a8900e4e7c7c3ba59db where T:class where U:struct ,T   T為引用型別為何與值型別一起約束U?

希望可以指正

# 以上就是C# 泛型的約束圖文詳細介紹的內容,更多相關內容請關注PHP中文網(www.php.cn)!


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn