泛型--协变与逆变(转)
對(duì)于泛型的知識(shí),一直比較模糊,現(xiàn)在有機(jī)會(huì)整理一下,突發(fā)發(fā)現(xiàn)C#還有很多你不知道的東東,繼續(xù).NET FrameWork中泛型的協(xié)變與逆變:
1. 可變性的類(lèi)型:協(xié)變性和逆變性
可變性是以一種類(lèi)型安全的方式,將一個(gè)對(duì)象當(dāng)做另一個(gè)對(duì)象來(lái)使用。如果不能將一個(gè)類(lèi)型替換為另一個(gè)類(lèi)型,那么這個(gè)類(lèi)型就稱(chēng)之為:不變量。協(xié)變和逆變是兩個(gè)相互對(duì)立的概念:
- 如果某個(gè)返回的類(lèi)型可以由其派生類(lèi)型替換,那么這個(gè)類(lèi)型就是支持協(xié)變的
- 如果某個(gè)參數(shù)類(lèi)型可以由其基類(lèi)替換,那么這個(gè)類(lèi)型就是支持逆變的。
2. C# 4.0對(duì)泛型可變性的支持
在C# 4.0之前,所有的泛型類(lèi)型都是不變量——即不支持將一個(gè)泛型類(lèi)型替換為另一個(gè)泛型類(lèi)型,即使它們之間擁有繼承關(guān)系,簡(jiǎn)而言之,在C# 4.0之前的泛型都是不支持協(xié)變和逆變的。
C# 4.0通過(guò)兩個(gè)關(guān)鍵字:out和in來(lái)分別支持以協(xié)變和逆變的方式使用泛型。
3. C#中泛型可變性的限制
1. 不支持類(lèi)的類(lèi)型參數(shù)的可變性
只有接口和委托可以擁有可變的類(lèi)型參數(shù)。in 和 out 修飾符只能用來(lái)修飾泛型接口和泛型委托。
2. 可變性只支持引用轉(zhuǎn)換
可變性只能用于引用類(lèi)型,禁止任何值類(lèi)型和用戶(hù)定義的轉(zhuǎn)換,如下面的轉(zhuǎn)換是無(wú)效的:
- 將 IEnumerable<int> 轉(zhuǎn)換為 IEnumerable<object> ——裝箱轉(zhuǎn)換
- 將 IEnumerable<short> 轉(zhuǎn)換為 IEnumerable<int> ——值類(lèi)型轉(zhuǎn)換
- 將 IEnumerable<string> 轉(zhuǎn)換為 IEnumerable<XName> ——用戶(hù)定義的轉(zhuǎn)換
3. 類(lèi)型參數(shù)使用了 out 或者 ref 將禁止可變性
對(duì)于泛型類(lèi)型參數(shù)來(lái)說(shuō),如果要將該類(lèi)型的實(shí)參傳給使用 out 或者 ref 關(guān)鍵字的方法,便不允許可變性,如:
delegate void someDelegate<in T>(ref T t)4. 可變性必須顯式指定
從實(shí)現(xiàn)上來(lái)說(shuō)編譯器完全可以自己判斷哪些泛型參數(shù)能夠逆變和協(xié)變,但實(shí)際卻沒(méi)有這么做,這是因?yàn)镃#的開(kāi)發(fā)團(tuán)隊(duì)認(rèn)為:
必須由開(kāi)發(fā)者明確的指定可變性,因?yàn)檫@會(huì)促使開(kāi)發(fā)者考慮他們的行為將會(huì)帶來(lái)什么后果,從而思考他們的設(shè)計(jì)是否合理。
5. 注意破壞性修改
在修改已有代碼接口的可變性時(shí),會(huì)有破壞當(dāng)前代碼的風(fēng)險(xiǎn)。例如,如果你依賴(lài)于不允許可變性的is或as操作符的結(jié)果,運(yùn)行在.NET 4時(shí),代碼的行為將有所不同。同樣,在某些情況下,因?yàn)橛辛烁嗫捎玫倪x項(xiàng),重載決策也會(huì)選擇不同的方法。所以在對(duì)已有代碼引入可變性時(shí)要做好足夠的單元測(cè)試以及防御措施。
6. 多播委托與可變性不能混用
下面的代碼能夠通過(guò)編譯,但是在運(yùn)行時(shí)會(huì)拋出 ArgumentException 異常:
Func<string> stringFunc = () => ""; Func<object> objectFunc = () => new object(); Func<object> combined = objectFunc + stringFunc;這是因?yàn)樨?fù)責(zé)鏈接多個(gè)委托的 Delegate.Combine方法要求參數(shù)必須為相同的類(lèi)型。上面的示例我們可以修改成如下正確的代碼:
Func<string> stringFunc = () => ""; Func<object> defensiveCopy = new Func<object>(stringFunc); Func<object> objectFunc = () => new object(); Func<object> combined = objectFunc + defensiveCopy;?推薦文章:
http://www.cnblogs.com/oujinliang/archive/2009/11/30/1613985.html
IOC推薦:
http://developer.51cto.com/art/201107/276775_all.htm
轉(zhuǎn)載于:https://www.cnblogs.com/xibei666/p/5451793.html
總結(jié)
以上是生活随笔為你收集整理的泛型--协变与逆变(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: parseInt(),parseFloa
- 下一篇: RX