最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳析C#的協(xié)變和逆變

 更新時間:2022年01月07日 10:29:27   作者:返回主頁RyzenAdorer  
這篇文章主要介紹了詳析C#的協(xié)變和逆變,在引用類型系統(tǒng)時,協(xié)變、逆變和不變性具有如下定義。?這些示例假定一個名為?Base?的基類和一個名為?Derived的派生類,更多內(nèi)容請需要的小伙伴參考下面文章內(nèi)容

前言:

在引用類型系統(tǒng)時,協(xié)變、逆變和不變性具有如下定義。 這些示例假定一個名為 Base 的基類和一個名為 Derived的派生類。

Covariance

使你能夠使用比原始指定的類型派生程度更大的類型。

你可以將 IEnumerable 的實例分配給 IEnumerable 類型的變量。

Contravariance

使你能夠使用比原始指定的類型更泛型(派生程度更小)的類型。

你可以將 Action 的實例分配給 Action 類型的變量。

Invariance

表示只能使用最初指定的類型。 固定泛型類型參數(shù)既不是協(xié)變,也不是逆變。

你無法將 List 的實例分配給 List 類型的變量,反之亦然。

以上來自于官方文檔對協(xié)變、逆變、不變性的解釋

為啥C#需要協(xié)變和逆變?

我們首先來看一段代碼:

class FooBase{ }

class Foo : FooBase?
{

}

var foo = new Foo();
FooBase fooBase = foo;

//以下代碼在.NET 4.0之前是不被支持的
IEnumerable<Foo> foo = new List<Foo>();
IEnumerable<FooBase> fooBase = foo;

因此,在這里實際上可以回答,C#的協(xié)變和逆變就是主要有兩種目的:

  • 兼容性:.NET2.0就推出了泛型,而從.NET 2.0到.NET 3.5期間不支持對泛型接口中的占位符T支持隱式轉(zhuǎn)換,因此在.NET4.0推出協(xié)變和逆變
  • 為了支持更廣泛的隱式類型的轉(zhuǎn)換,在這里就是在泛型體系中支持

在C#中,目前只有泛型接口和泛型委托可以支持協(xié)變和逆變,

協(xié)變(Covariance)

內(nèi)置的泛型協(xié)變接口,IEnumerator、IQuerable、IGrouping

 ? public interface IEnumerable<out T> : IEnumerable
? ? {
? ? ? ? new IEnumerator<T> GetEnumerator();
? ? }


? ? public interface IQueryable<out T> : IEnumerable<T>, IEnumerable, IQueryable
? ? {

? ? }


? ? public interface IGrouping<out TKey, out TElement> : IEnumerable<TElement>, IEnumerable
? ? {
? ? ? TKey Key { get; }
? ? }

因此這段代碼在.NET4.0及以上版本將不會編譯報錯:

IEnumerable<Foo> foo = new List<Foo>();
IEnumerable<FooBase> fooBase = foo;

實際上,對于協(xié)變,有下面的約束,否則則會在編譯時報錯:

  • 泛型參數(shù)占位符以out關(guān)鍵子標(biāo)識,并且占位符T只能用于只讀屬性、方法或者委托的返回值,out簡而易懂,就是輸出的意思
  • 當(dāng)要進行類型轉(zhuǎn)換,占位符T要轉(zhuǎn)換的目標(biāo)類型也必須是其基類,上述例子則是Foo隱式轉(zhuǎn)為FooBase

逆變(Contravariance)

內(nèi)置的泛型逆變委托Action、Func、Predicate,內(nèi)置的泛型逆變接口IComparable<T>、IEquatable<T>:

? public delegate void Action<in T>(T obj);

? public delegate TResult Func<in T, out TResult>(T arg);

? public delegate bool Predicate<in T>(T obj);


? public interface IComparable<in T>
? {
? ? int CompareTo(T? other);
? }

? public interface IEquatable<T>
? {
? ? bool Equals(T? other);
? }

而逆變的用法則是這樣:

Action<FooBase> fooBaseAction = new Action<FooBase>((a)=>Console.WriteLine(a));

Action<Foo> fooAction = fooBaseAction;

而對于逆變,則跟協(xié)變相反,有下面的約束,否則也是編譯時報錯:

要想標(biāo)識為逆變,應(yīng)該是要在占位符T前標(biāo)識in,只能用于只寫屬性、方法或者委托的輸入?yún)?shù)
當(dāng)要進行類型轉(zhuǎn)換,占位符T要轉(zhuǎn)換的目標(biāo)類型也必須是其子類,上述例子則是FooBase轉(zhuǎn)為Foo
總結(jié)#
協(xié)變和逆變只對泛型委托和泛型接口有效,對普通的泛型類和泛型方法無效
協(xié)變和逆變的類型必須是引用類型,因為值類型不具備繼承性,因此類型轉(zhuǎn)換存在不兼容性
泛型接口和泛型委托可同時存在協(xié)變和逆變的類型參數(shù),即占位符T

到此這篇關(guān)于詳析C#的協(xié)變和逆變的文章就介紹到這了,更多相關(guān)C#的協(xié)變和逆變內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

南开区| 临洮县| 荣成市| 安达市| 吴江市| 海林市| 威宁| 曲周县| 文昌市| 长乐市| 安宁市| 湖州市| 汝州市| 惠水县| 扎赉特旗| 二手房| 宜兰县| 嘉义市| 兴安县| 鄂托克前旗| 铜鼓县| 华容县| 玉环县| 阿瓦提县| 赣榆县| 德格县| 高陵县| 广南县| 公安县| 侯马市| 太康县| 芮城县| 无棣县| 会昌县| 焉耆| 交口县| 宁陵县| 淮阳县| 宜都市| 宣汉县| 阿坝|