欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

前言:

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

Covariance

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

你可以將 IEnumerable 的實(shí)例分配給 IEnumerable 類(lèi)型的變量。

Contravariance

使你能夠使用比原始指定的類(lèi)型更泛型(派生程度更?。┑念?lèi)型。

你可以將 Action 的實(shí)例分配給 Action 類(lèi)型的變量。

Invariance

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

你無(wú)法將 List 的實(shí)例分配給 List 類(lèi)型的變量,反之亦然。

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

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

我們首先來(lái)看一段代碼:

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;

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

  • 兼容性:.NET2.0就推出了泛型,而從.NET 2.0到.NET 3.5期間不支持對(duì)泛型接口中的占位符T支持隱式轉(zhuǎn)換,因此在.NET4.0推出協(xié)變和逆變
  • 為了支持更廣泛的隱式類(lèi)型的轉(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及以上版本將不會(huì)編譯報(bào)錯(cuò):

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

實(shí)際上,對(duì)于協(xié)變,有下面的約束,否則則會(huì)在編譯時(shí)報(bào)錯(cuò):

  • 泛型參數(shù)占位符以out關(guān)鍵子標(biāo)識(shí),并且占位符T只能用于只讀屬性、方法或者委托的返回值,out簡(jiǎn)而易懂,就是輸出的意思
  • 當(dāng)要進(jìn)行類(lèi)型轉(zhuǎn)換,占位符T要轉(zhuǎn)換的目標(biāo)類(lèi)型也必須是其基類(lèi),上述例子則是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;

而對(duì)于逆變,則跟協(xié)變相反,有下面的約束,否則也是編譯時(shí)報(bào)錯(cuò):

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

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

相關(guān)文章

  • C#特性-對(duì)象集合初始化器介紹

    C#特性-對(duì)象集合初始化器介紹

    在寫(xiě)一些實(shí)體類(lèi)的時(shí)候,我們往往在寫(xiě)構(gòu)造方法的時(shí)候思考很長(zhǎng)時(shí)間,除了一個(gè)無(wú)參構(gòu)造器外還在想需要寫(xiě)幾個(gè)構(gòu)造器呢?哪些參數(shù)是需要初始化的。現(xiàn)在你再也不需要為這事煩惱了
    2014-12-12
  • c#對(duì)XML文檔的創(chuàng)建與增刪改查的示例代碼

    c#對(duì)XML文檔的創(chuàng)建與增刪改查的示例代碼

    這篇文章主要介紹了c#對(duì)XML文檔的創(chuàng)建與增刪改查的示例代碼,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • C# 如何實(shí)現(xiàn)Token

    C# 如何實(shí)現(xiàn)Token

    這篇文章主要介紹了C# 如何實(shí)現(xiàn)Token,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-03-03
  • C#多線程之線程綁定ThreadLocal類(lèi)

    C#多線程之線程綁定ThreadLocal類(lèi)

    這篇文章介紹了C#多線程之線程綁定ThreadLocal類(lèi)的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • c# 如何實(shí)現(xiàn)不同進(jìn)程之間的通信

    c# 如何實(shí)現(xiàn)不同進(jìn)程之間的通信

    這篇文章主要介紹了c# 如何實(shí)現(xiàn)不同進(jìn)程之間的通信,幫助大家更好的理解和學(xué)習(xí)c#,感興趣的朋友可以了解下
    2020-11-11
  • vs 中C#項(xiàng)目讀取JSON配置文件的方法

    vs 中C#項(xiàng)目讀取JSON配置文件的方法

    這篇文章主要介紹了vs中 C#項(xiàng)目讀取JSON配置文件的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • .net實(shí)現(xiàn)序列化與反序列化實(shí)例解析

    .net實(shí)現(xiàn)序列化與反序列化實(shí)例解析

    這篇文章主要介紹了.net實(shí)現(xiàn)序列化與反序列化實(shí)例解析,需要的朋友可以參考下
    2014-08-08
  • DevExpress之TreeList用法實(shí)例總結(jié)

    DevExpress之TreeList用法實(shí)例總結(jié)

    這篇文章主要介紹了DevExpress之TreeList用法,對(duì)于C#初學(xué)者有一定的借鑒價(jià)值,需要的朋友可以參考下
    2014-08-08
  • C#讀取數(shù)據(jù)庫(kù)返回泛型集合詳解(DataSetToList)

    C#讀取數(shù)據(jù)庫(kù)返回泛型集合詳解(DataSetToList)

    本篇文章主要是對(duì)C#讀取數(shù)據(jù)庫(kù)返回泛型集合(DataSetToList)進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2014-01-01
  • Unity實(shí)現(xiàn)批量Build打包詳解

    Unity實(shí)現(xiàn)批量Build打包詳解

    一般來(lái)講如果項(xiàng)目是PC或Android、IOS端不會(huì)有批量Build打包這樣的需求,但如果項(xiàng)目是WebGL端可能會(huì)遇到這樣的需求。本文主要為大家介紹Unity中如何實(shí)現(xiàn)Build批量打包的,需要的朋友可以參考一下
    2021-12-12

最新評(píng)論