網站首頁 編程語言 正文
1、什么是協變、逆變?
假設:TSub是TParent的子類。
協變:如果一個泛型接口IFoo
逆變:如果一個泛型接口IFoo
2、為什么要有協變、逆變?
通常只有具備繼承關系的對象才可以發生隱式類型轉換,如Base b=new sub()。
協變和逆變可以使得更多的類型之間能夠實現隱式類型轉換、類型安全性有了保障。
3、為什么泛型接口要引入協變、逆變?
基于以上原因的同時、許多接口僅僅將類型參數用于參數或返回值。所以支持協變和逆變后泛型的使用上有了更大的靈活性
4、為什么支持協變的參數只能用于方法的返回值?支持逆變的參數只能用于方法參數?
“TParent不能安全轉換成TSub”,是這兩個問題的共同原因。
我們定義一個接口IFoo。
interface IFoo{ void Method1(T param); T Method2(); }
我們看一下協變的過程:IFoo
- Method1:將TSub替換成TParent,Method1顯然存在 TParent到TSub的轉換。
- Method2:返回值類型從TSub換成了TParent,是類型安全的。
所以支持協變的參數只能用在方法的返回值中。
再看一下逆變的過程:IFoo
- Method1:將TParent替換成TSub,Method1存在 TSub到TParent的轉換,是類型安全的。
- Method2:返回值類型從TParent換成了TSub,是不安全的。
所以支持逆變的參數只能用在方法的參數中。
5、泛型接口支持協變、逆變和不支持協變、逆變的對比?
這其實是對3個問題的補充。
定義一個接口IFoo,既不支持協變,也不支持逆變。
interface IFoo{ void Method1(T param); T Method2(); }
實現接口IFoo
public class FooClass: IFoo { public void Method1(T param) { Console.WriteLine(default(T)); } public T Method2() { return default(T); } }
定義一個接口IBar支持對參數T的協變
interface IBar{ T Method(); }
實現接口IBar
public class BarClass: IBar { public T Method() { return default(T); } }
?定義一個接口IBaz支持對參數T的逆變
interface IBaz{ void Method(T param); }
實現接口IBaz
public class BazClass: IBaz { public void Method(T param) { Console.WriteLine(param.ToString()); } }
定義兩個有繼承關系的類型,IParent和SubClass。
interface IParent { void DoSomething(); } public class SubClass : IParent { public void DoSomething() { Console.WriteLine("SubMethod"); } }
按照協變的邏輯,分別來使用IFoo和IBar。
//IFoo 不支持對參數T的協變 IFoofoo_sub = new FooClass (); IFoo foo_parent = foo_sub;//編譯錯誤 //IBar 支持對參數T的協變 IBar bar_sub = new BarClass (); IBar bar_parent = bar_sub;
foo_parent?=?foo_sub 會提示編譯時錯誤“無法將類型“IFoo
”隱式轉換為“IFoo ”。存在一個顯式轉換(是否缺少強制轉換?)”
按照逆變的邏輯,分別來使用IFoo和IBaz。
//IFoo 對參數T逆變不相容 IFoofoo_parent = null; IFoo foo_sub = foo_parent;//編譯錯誤 //IBaz 對參數T逆變相容 IBaz baz_parent = null; IBaz baz_sub = baz_parent;
?foo_sub?=?foo_parent 會提示編譯時錯誤“無法將類型“IFoo
”隱式轉換為“IFoo ”。存在一個顯式轉換(是否缺少強制轉換?)”
6、.NET4.0對IEnumerable接口的修改?
2.0中的定義:
public interface IEnumerable: IEnumerable { IEnumerator GetEnumerator(); }
4.0中的定義:
public interface IEnumerable: IEnumerable { IEnumerator GetEnumerator(); }
可以看到4.0中增加了對協變的支持。
可以在兩個版本試下, 下面的語句在2.0下會報錯。
Listsubarr = new List (); IEnumerable parentarr = subarr;
原文鏈接:https://www.cnblogs.com/tenghoo/archive/2012/12/04/interface_covariant_contravariant.html
相關推薦
- 2022-05-10 axios方式發送ajax,語法類似,但更簡單
- 2023-07-05 DateUtils 日期工具類
- 2022-05-20 ASP.NET?MVC項目部署方式介紹_基礎應用
- 2022-12-06 python中isdigit()?isalpha()用于判斷字符串的類型問題_python
- 2022-07-30 jQuery?UI工具提示框部件Tooltip?Widget_jquery
- 2022-04-27 ASP.NET?Core中的策略授權和ABP授權_實用技巧
- 2022-07-18 spring boot 中解決 Invalid character found in the req
- 2022-11-16 python壓縮和解壓縮模塊之zlib的用法_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支