6)協變和反變(co-variant & crop-variant)
這是vs2010新增的乙個內容,用於在編譯的時候確認是否允許不同型別的泛型介面之間是否存在轉換的問題。
為了了解「協變」和「反變」的概念,我們先看乙個例子:
假設我們定義了乙個介面和若干類:
class father
public virtual void say()
console.writeline("father");
class son : father
public override void say()
console.writeline("son");
class son2 : father
public override void say()
console.writeline("son2");
inte***ce inandout
void input(v value);
t output();
class program:inandout
private object value = default(v);
public t output()
return (t)value;
public void input(v tv)
value = tv;
又假如我們已經例項化兩個介面的例項:
inandoutiobj1 = new program < father, son >();
inandoutiobj2 = new program < son, father >();
現在我們令:iobj1= iobj2,可行嗎?
乍一看似乎可行——為什麼呢?因為聯想到右邊的兩個子類son會被自動隱式轉化成其父類father。就好像是father f = new son()一樣可以(注意:我們把子類隱式轉化成父類成為「協變」,反之成為「反變」)。而且,根據介面定義,輸入方向是接受乙個son(實際儲存在iobj2中,被隱式轉成father),輸出的時候還是儲存的son被隱式轉化成father輸出。
這種思考邏輯固然沒有錯,但是它有乙個前提條件——即從iobj1輸入方向看,必須是son到father,輸出的話也必須是son到father!但是泛型僅僅是乙個定義,誰能夠保證在類中father或者son一定是輸入(或者是輸出)引數呢?如果我們改變成以下的形式呢?
class program:inandout
private object value = default(t);
public v output()
return (v) value;
public void input(t tv)
value = tv;
這樣就出現了問題——首先,iobj1指向iobj2(接受乙個father的引數,此時如果我的father輸入的是son2,那麼實際轉化到son的時候就發生異常了;同樣地,輸出因為是son2不能轉化成son,因此發生異常)。
這個問題就是因為輸入輸出方向不明確所導致的。如果我們強制是一開始就給出的輸入(輸出方向)。即v只能作為輸入,t只能作為輸出就可以了。
推而廣之,假設存在兩個泛型t和v,假設v:t(v是tout,輸入加in。如下所示:
inte***ce inandout
void input(v value);
t output();
那麼你輸入以下**,就可以輸出結果:
inandoutiobj1 = new program < father, son >();
inandoutiobj2 = new program < son, father >();
這種規則本質上是編譯器的行為理解。但是不一定就是正確結果,考察下列例子:
inandoutiobj1 = new program < father, son >();
inandoutiobj2 = new program < son2, father >();
這一段**照樣可以通過編譯,但是執行仍舊報異常。為什麼呢?因為「輸入端」和「輸出端」儘管都符合了隱式轉換的條件,但是你注意:把乙個son物件儲存到iobj2的時候,iboj2的輸出要求是son2,而不是son! 因此要保證執行正確,必須做到這樣:
inandout<father, son> iobj1 = new program < father, son >();
inandout<son, father> iobj2 = new program < son, father >();
輸入端接受son,能夠隱式轉成藍色的father,藍色father儲存的子類物件同樣必須可以轉化成son(即乙個協變的東西必須能夠支援其反變;反之,乙個反變的泛型必須支援其協變泛型,這就是著名的「協變反變型別」,簡稱「協-反變型別」)。
證明:(紅色的son開始):隱式轉化成father(協變),然後藍色的father(其中儲存son)強制轉化成綠色的son(反變)。
同理,(黑色的father開始):黑色father返回的內容(儲存son)可以強制轉化成藍色father的內容(反變),同時可以隱式轉化成綠色son(協變)。我覺得可以使用對角線規則驗證(猜想,對於任意的泛型a,b,c,d):
inandout<a,b>
(b既可以轉成d,也可以轉成c;輸出a包含的內容
可以轉化成d,也可以轉化成c)
inandout<c, d>
C 4 0和VS2010新特性
dynamic初探 以前因為某些特殊原因,需要動態的呼叫外部類 假設這個類是實現了某個帶有引數的介面函式的 通常我們只能用反 示例 如下 assembly asm assembly.loadfile xx asm.createinstance myassembly.classname gettype...
C 4 0和VS2010新特性(三)
vs2010之所以那麼強大,究其原因是其背後有著強大的c 4.0作為後台支撐。和以往的所有版本相比,c 4.0的動態性大大增強 dynamic就是乙個非常明顯的例子 一 dynamic初探 以前因為某些特殊原因,需要動態的呼叫外部類 假設這個類是實現了某個帶有引數的介面函式的 通常我們只能用反 示例...
vs2010與C 4 0新特性
vs2010被認為將是續寫visual studio 6 的扛鼎之作。整個ide不僅是使用了wpf重構,而且使用了最新的net framework 4作為強大的後援支撐。從上至下可圈可點。下面我們就來看一看vs2010在哪些方面引人注目 1 wpf重構介面 整個vs2010 ide全部使用wpf重構...