泛型的約束理解
1.引用型別約束
struct RefSample<T> where T:class
引用型別用Class
表示約束,其他的引用型別為具體的約束。
表示對於的約束必須為一個類(引用型別)不能是值型別(int,char,datatime,struct
),可以是介面interface
區分,陣列為引用型別,因為定義陣列時需要new
出一個物件。
雖然定義成 RefSample<T>
傳入的必須為引用型別 但是RefSample
仍然為值型別
2.值型別約束
class ValSample<T> where T:struct
為引用型別,因為int
,char
等型別都是struct
ValSample<int>
3.建構函式型別約束
public T CreateInstance<T>() where T:new()
{
return new T();
}
指定的型別T
必須有建構函式,CreateInstance<int>
和CreateInstance<object>
都是有效的。但是CreateInstance<strings>
沒有建構函式。
4.轉換型別約束
一種約束允許你指定另一個型別,型別實參必須可以通過一致性、引用或裝箱轉換隱式地轉換為該型別。你還可以規定一個型別實參必須可以轉換為另一個型別實參——這稱為型別引數約束。
理解的意思:可以互換,就是我們可以通過裝箱或者強制型別轉換成目標型別的 型別都可以用於型別引數傳入。
class Sample<T> where T:Stream
有效:Sample<Stream>
這本身符合約束
無效:Sample<String>
因為String
型別無法通過引用或者裝箱拆箱強制轉換成Stream、
struct Sample<T> where T:IDisposable
規定T必須為IDisposable
型別的 引用型別
有效:Sample<SqlConnection>
引用轉換
無效:Sample<StringBuilder>
分析:為什麼SqlConnection
可以而StringBuilder
不可以?它們都是引用型別
1.SqlConnection
實現了IDisposable
介面,所以可以協變
2.StringBuilder
只實現了ISerializable
介面,無法通過途徑轉換為IDisposable
class Sample<T> where T:IComparable<T>
因為將IComparable<T>
整體當作約束,分析IComparable<T>
的型別,可以用Type.IsValueType
判斷,true
為值型別,false
為引用型別
typeof(IComparable<T>).IsValueType
結果為false
表示為引用型別
有效:Sample<int>
(裝箱轉換)
無效:Sample<FileInfo>
也可以指定多種約束:
class sample<T> where T:stream,IEnumerable<string>,IComparable<int>
class Sample<T,U> where T:U
有效:Sample<Stream,IDisposable>
無效:Sample<string,IDiposable>
總結:要看傳入類引數是否可以轉換,檢視規定引數和傳入類引數是否實現同一介面,如果實現則可以,否則不可以。
不可以是以下:System.Object,System.Enum,System.ValueType,System.Delegate
,結構或密封類(String
)
5.組合約束
對型別引數的約束有多個,注意:只能是一種型別,值型別和引用型別不能同時存在,沒用一個型別即是引用型別,又是值型別。
由於每一個值型別都有一個無建構函式,此後不能再有建構函式約束
有效:
class Sample<T> where T:class,IDisposable,new()
class Sample<T,U> where T:Stream where U:IDispsable
無效:
class Sample<T> where T:class,struct
(沒有任何型別即時引用型別又是值型別的,所以為無效的)
class Sample<T> where T:Stream,class
(引用型別約束應該為第一個約束,放在最前面,所以為無效的) Stream
只是約束傳入引數為Stream
具體型別,而class
約束為引用型別,一開始我理解錯了
class Sample<T> where T:new(),Stream
(new()
必須放在最後)
class Sample<T> where T:IDisposable,Stream
(類必須放在介面前面,所以為無效的)
class Sample<T> where T:XmlReader,IComparable,IComparable
(對於轉換型別約束,同一個介面不能出現多次)
class Sample<T,U> where T:struct where U:Class,T
(型別形參“T”具有“struct”約束,因此“T”不能用作“U”的約束,所以為無效的)
class Sample<T,U> where T:Stream ,U:IDisposable
語法錯誤
看到網上還有這種版本也是有效的我表示不理解:
class Sample<T> where T:struct,IDisapsable IDisapsable
為值型別?
class Sample<T,U> where T:class where U:struct ,T
T
為引用型別為何與值型別一起約束U
?
希望可以指正
相關文章
- Go 泛型之泛型約束Go泛型
- C#泛型約束C#泛型
- C# 泛型 引用型別約束 值型別約束C#泛型型別
- C# 泛型 介面約束C#泛型
- C# 泛型 基類約束C#泛型
- C#中泛型約束(where)是什麼?C#泛型
- C# 泛型 new()建構函式約束C#泛型函式
- Java泛型(三):型別擦除帶來的約束與侷限性Java泛型型別
- 16.Kotlin星投影與泛型約束詳解Kotlin泛型
- 【.NET】利用 IL 魔法實現隨心隨意的泛型約束泛型
- [譯]Kotlin泛型中何時該用型別形參約束?Kotlin泛型型別
- 我理解的 Java 泛型Java泛型
- 學員優秀博文賞析:泛型萬用字元及約束泛型字元
- 差分約束的一些理解
- PHP7型別約束PHP型別
- SQL教程——常見的約束型別SQL型別
- PHP中的型別約束介紹PHP型別
- Java泛型理解與使用Java泛型
- 深入理解 Java 泛型Java泛型
- 深入理解Java泛型Java泛型
- 【泛型——這才真正的理解你】泛型
- 【SQL】15 SQL 約束(Constraints)、NOT NULL 約束、UNIQUE 約束、PRIMARY KEY 約束、FOREIGN KEY 約束、CHECK 約束、DEFAULT約束SQLAINull
- TreeSet的null值與元素型別的約束Null型別
- 常見問題--表的約束initially immediate 理解
- 【譯】Flutter | 深入理解佈局約束Flutter
- 深度學習中的Lipschitz約束:泛化與生成模型深度學習模型
- Oracle constraints type 約束型別OracleAI型別
- Java泛型的理解與等價實現Java泛型
- C#基礎:泛型的理解和使用C#泛型
- Go 泛型變更:約束太醜了,先移動到 x/exp 做實驗性功能Go泛型
- 理解C#泛型運作原理C#泛型
- Java基礎——深入理解泛型Java泛型
- 一文理解TS泛型泛型
- 對.NET2.0泛型初步理解泛型
- 泛型--泛型萬用字元和泛型的上下限泛型字元
- Javaweb-約束-外來鍵約束JavaWeb
- C#泛型的逆變協變(個人理解)C#泛型
- Java 泛型的理解與等價實現薦Java泛型