協(xié)變和逆變使我們在處理類層次結(jié)構(gòu)時更加靈活。
在學(xué)習(xí)協(xié)變和逆變之前,請看以下類層次結(jié)構(gòu):
public class Small
{
}
public class Big: Small
{
}
public class Bigger : Big
{
}根據(jù)上面的示例類,Small 是 Big 的基類,而Big 是 Bigger 的基類。這里要記住的一點是,派生類將始終具有比基類更多的東西,因此基類比派生類要小。
現(xiàn)在,看以下初始化:

如上所示,基類可以容納派生類,但派生類不能容納基類。換句話說,一個實例即使要求很小也可以接受大,但是如果要求很大就不能接受小。
現(xiàn)在,讓我們了解協(xié)變和逆變。
協(xié)變使您能夠傳遞派生類型,其中需要基類型。協(xié)變就像同類型的方差。基類和其他派生類被認(rèn)為是向基類型添加額外功能的同類類。因此,協(xié)變允許您在需要基類的地方使用派生類(如果需要小類,則 rule: 可以接受大類)。
協(xié)變可以應(yīng)用于委托,泛型,數(shù)組,接口等。
委托中的協(xié)變允許委托方法的返回類型具有靈活性。
public delegate Small covarDel(Big mc);
public class Program
{
public static Big Method1(Big bg)
{
Console.WriteLine("Method1");
return new Big();
}
public static Small Method2(Big bg)
{
Console.WriteLine("Method2");
return new Small();
}
public static void Main(string[] args)
{
covarDel del = Method1;
Small sm1 = del(new Big());
del= Method2;
Small sm2 = del(new Big());
}
}Method1 Method2
如您在上面的示例中看到的那樣,委托期望返回的類型為 Small(基類),但是我們?nèi)匀豢梢苑峙浞祷谺ig(派生類)的Method1以及具有與委托期望的簽名相同的Method2。
因此,協(xié)變允許您將方法分配給具有較少派生返回類型的委托。
將Contravariane(逆變)應(yīng)用于參數(shù)。 Cotravariance(逆變) 允許將基類參數(shù)分配給希望派生類參數(shù)的委托的方法。
繼續(xù)上面的示例,添加具有與委托不同的參數(shù)類型的Method3:
delegate Small covarDel(Big mc);
class Program
{
static Big Method1(Big bg)
{
Console.WriteLine("Method1");
return new Big();
}
static Small Method2(Big bg)
{
Console.WriteLine("Method2");
return new Small();
}
static Small Method3(Small sml)
{
Console.WriteLine("Method3");
return new Small();
}
static void Main(string[] args)
{
covarDel del = Method1;
del += Method2;
del += Method3;
Small sm = del(new Big());
}Method1 Method2 Method3
如您看到的,Method3具有Small類的參數(shù),而委托則期望Big類的參數(shù)。 不過,您可以將Method3與委托一起使用。
您還可以按如下所示的相同方法使用協(xié)變和逆變。
delegate Small covarDel(Big mc);class Program
{ static Big Method4(Small sml)
{ Console.WriteLine("Method3");
return new Big();
} static void Main(string[] args)
{ covarDel del = Method4;
Small sm = del(new Big());
}
}Method4