C#实现协变和逆变案例

 更新时间:2022年10月22日 14:16:53   作者:Darren Ji  
这篇文章介绍了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(); 

可见,在方法中基于派生类接口类型的形参,调用该方法的时候可以传入基类接口类型的实参。 

总结:在本篇的场景中,派生类接口替代父类接口,称之为协变;父类接口代替派生类接口,称之为逆变。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

相关文章

  • C#中把Json数据转为DataTable

    C#中把Json数据转为DataTable

    这篇文章介绍了C#中把Json数据转为DataTable的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • 深入浅析C#中的var和dynamic

    深入浅析C#中的var和dynamic

    这篇文章给大家介绍了C#中的var和dynamic的相关知识,var和dynamic的本质区别是类型判断的时间不同,前者是编译时,后者是运行时。具体内容详情大家通过本文学习下吧
    2018-05-05
  • unity置灰处理的实现

    unity置灰处理的实现

    本文主要介绍了unity置灰处理的实现,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2021-07-07
  • c#求点到直线的投影点坐标

    c#求点到直线的投影点坐标

    这篇文章主要介绍了c#求直线外一点到该直线的投影点,大家参考使用吧
    2013-12-12
  • Winform使用FTP实现自动更新

    Winform使用FTP实现自动更新

    这篇文章主要为大家详细介绍了Winform使用FTP实现自动更新,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • 如何利用c#实现通用守护进程

    如何利用c#实现通用守护进程

    这篇文章主要给大家介绍了关于如何利用c#实现通用守护进程的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用c#具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-10-10
  • C#的静态工厂方法与构造函数相比有哪些优缺点

    C#的静态工厂方法与构造函数相比有哪些优缺点

    这篇文章主要介绍了C#的静态工厂方法与构造函数对比的优缺点,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • C#/.net程序调用Python的教程分享

    C#/.net程序调用Python的教程分享

    C#的优势在于window下的开发,不仅功能强大而且开发周期短。而python则有众多的第三方库,可以避免自己造轮子,利用C#来做界面,而具体实现使用python来实现可以大大提高开发效率。本文介绍如何使用pythonnet来执行python脚本,希望对大家有所帮助
    2023-03-03
  • C# SynchronizationContext以及Send和Post使用解读

    C# SynchronizationContext以及Send和Post使用解读

    这篇文章主要介绍了C# SynchronizationContext以及Send和Post使用解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • 比较有效的使用C#读取文件的代码

    比较有效的使用C#读取文件的代码

    比较有效的使用C#读取文件的代码...
    2007-08-08

最新评论