C# 協變、逆變


微軟官方概述:

在C#中,協變和逆變能夠實現數組類型、委托類型和泛型類型參數的隱式引用轉換。協變保留分配兼容性,逆變則與之相反。

協變:能夠使用與原始指定的派生類型相比,派生程度更大的類型。

逆變:能夠使用派生程度更小的類型。

官方示例:

string str = "test";
object obj = str;

IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;

static void SetObject(object){}
Action<object> actObject = SetObject;
Action<string> actString = actObject;

上面示例中,從 string --> object 的隱式轉換這是協變;如果從 object --> string 轉換這是逆變。

數組協變

string[] str = new string[10];
object[] array = str;

這是一種不安全的操作,在對 array數組賦值時,array[0] = 0; 在編譯時可以通過,但是在運行時會提示錯誤。“System.ArrayTypeMismatchException:“嘗試訪問類型與數組不兼容的元素。””。這里的array 只是保存了str的引用,仍然是一個string類型的數組。

委托中的協變和逆變

對方法組的協變和逆變支持將方法簽名與委托類型相匹配。這樣不僅可以將具有匹配簽名的方法分配給委托,還可以分配與委托類型指定的派生類型相比,返回派生程度更大的類型的方法(協變)或者如果方法所接受參數的派生類型所具有的程度小於委托類型指定的程度(逆變),也可將其分配給委托。這就包含泛型委托和非泛型委托。

class People {}
class Student:People{}
delegate People Method();
class Program
{


    People peopleMethod(){}
    Student studetnMethod(){}

    static void Test(){
        Method method = peopleMethod;
        Method method2 = studentMethod;
    }
}

上面的委托Method(),返回值類型是People,但是我們采用更加具體的student類型也是可以的,由student --> People類型的轉換,這是正常的多態行為。委托的目標方法可能返回比委托聲明的返回值類型更加特定的返回值類型,這稱為協變。

那么當我們也可以采用一個比目標方法參數類型更加具體的參數類型,這稱為逆變。
下面的示例:

delegate void StringAction (string s);

class Test{
    static void Main(){
        StringAction sa = new StringAction (ActionObject);
        sa("hi");
        
    }
    static void ActionObject(object o) => Console.WriteLine(o);
}

C# 4.0添加了 out 和 in 關鍵字,來分別支持協變和逆變。

泛型中的協變和逆變,單獨介紹


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM