C#实现协变和逆变案例
关于协变逆变,SolidMango的解释是比较可取的。有了协变,比如,在需要返回IEnumerable<object>类型的时候,可以使用IEnmerable<string>来替代;有了逆变,比如,在需要接收IComparable<string>类型形参方法中,可以使用IComparable<object>类型实参来替代。
协变
先来体会协变。有2个具有继承关系的父类和子类。
public class Animal
{
public string Name { get; set; }
}
public class Dog : Animal
{
public Dog(string dogName)
{
Name = dogName;
}
}
现在有一个帮助类的方法的形参类型是父类集合IEnumerable<Animal>。
public class MyHelper
{
public void PrintAnimalNames(IEnumerable<Animal> animals)
{
foreach (var animal in animals)
{
Console.WriteLine(animal.Name);
}
}
}
有了协变,可以在PrintAnimalNames方法中传入IEnumerable<Dog>类型的实参替代IEnumerable<Animal>类型。
static void Main(string[] args)
{
List<Dog> dogs = new List<Dog>()
{
new Dog("小狗petty"),
new Dog("小狗lily")
};
//协变
IEnumerable<Animal> animals = dogs;
MyHelper myHelper = new MyHelper();
myHelper.PrintAnimalNames(animals);
Console.ReadKey();
}
可见,在方法中基于基类接口类型的形参,调用该方法的时候可以传入派生类接口类型的实参。
逆变
再来体会逆变。依然是2个具有继承关系的父类和子类。
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Cat : Animal
{
public Cat(string catName, int catAge)
{
Name = catName;
Age = catAge;
}
}
现在,我们想比较基类Animal的两个实例,为此,有必要专门写一个类让他实现IComparer<Animal>接口。
public class AnimalSizeComparator : IComparer<Animal>
{
public int Compare(Animal x, Animal y)
{
if (x != null && y != null)
{
if (x.Age > y.Age)
{
return 1;
}
else if (x.Age == y.Age)
{
return 0;
}
else
{
return -1;
}
}
else
{
return -1;
}
}
}
在帮助类中的方法中,针对Cat进行比较,方法接收IComparer<Cat>类型的形参。
public class MyHelper
{
public void CompareCats(IComparer<Cat> catComparer)
{
var cat1 = new Cat("小猫1",1);
var cat2 = new Cat("小猫2",2);
if (catComparer.Compare(cat2, cat1) > 0)
{
Console.WriteLine("小猫2胜出");
}
else
{
Console.WriteLine("小猫1胜出");
}
}
}
有了逆变,客户端调用MyHelper的CompareCats方法时,可以传入IComparer<Animal>类型的实参。
IComparer<Animal> animalComparer = new AnimalSizeComparator();
MyHelper myHelper = new MyHelper();
myHelper.CompareCats(animalComparer);
Console.ReadKey();
可见,在方法中基于派生类接口类型的形参,调用该方法的时候可以传入基类接口类型的实参。
总结:在本篇的场景中,派生类接口替代父类接口,称之为协变;父类接口代替派生类接口,称之为逆变。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对编程网的支持。如果你想了解更多相关内容请查看下面相关链接
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341