SoFunction
Updated on 2025-03-07

C# implements covariance and inverse cases

About covariance inversion,SolidMangoThe explanation is preferable. With covariance, for example, when you need to return the IEnumerable<object> type, you can use IEnmerable<string> as a substitute; with inversion, for example, when you need to receive the IComparable<string> type formal parameter method, you can use IComparable<object> type actual parameter to replace it.

Covariance

Let’s first experience covariance. There are 2 parent and child classes with inheritance relationships.

    public class Animal
    {
        public string Name { get; set; }
    }
    public class Dog : Animal
    {
        public Dog(string dogName)
        {
            Name = dogName;
        }
    }

Now there is a helper class method's formal parameter type is the parent class collection IEnumerable<Animal>.

    public class MyHelper
    {
        public void PrintAnimalNames(IEnumerable<Animal> animals)
        {
            foreach (var animal in animals)
            {
                ();
            }
        }
    }

With covariation, you can pass in the PrintAnimalNames method the argument of the IEnumerable<Dog> type instead of the IEnumerable<Animal> type.

        static void Main(string[] args)
        {
            List&lt;Dog&gt; dogs = new List&lt;Dog&gt;()
            {
                new Dog("Puppy petty"),
                new Dog("Puppy lily")
            };
            //Covariation            IEnumerable&lt;Animal&gt; animals = dogs;
            MyHelper myHelper = new MyHelper();
            (animals);
            ();
        }

It can be seen that in the method, based on the formal parameters of the base class interface type, the actual parameters of the derived class interface type can be passed in when calling this method.

Inversion

Let’s experience the inversion again. It is still 2 parent and child classes with inheritance relationships.

    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;
        }
    }

Now, we want to compare two instances of the base class Animal. For this reason, it is necessary to write a class specifically to enable it to implement the IComparer<Animal> interface.

    public class AnimalSizeComparator : IComparer<Animal>
    {
        public int Compare(Animal x, Animal y)
        {
            if (x != null && y != null)
            {
                if ( > )
                {
                    return 1;
                }
                else if ( == )
                {
                    return 0;
                }
                else
                {
                    return -1;
                }
            }
            else
            {
                return -1;
            }
        }
    }

In the method in the help class, the comparison is performed for Cat, and the method receives formal parameters of type IComparer<Cat>.

    public class MyHelper
    {
        public void CompareCats(IComparer&lt;Cat&gt; catComparer)
        {
            var cat1 = new Cat("Kitten 1",1);
            var cat2 = new Cat("Kitten 2",2);
            if ((cat2, cat1) &gt; 0)
            {
                ("Kitten 2 wins");
            }
            else
            {
                ("Kitten 1 wins");
            }
        }
    }

With inversion, when the client calls the CompareCats method of MyHelper, it can pass in the actual parameter of type IComparer<Animal>.

            IComparer<Animal> animalComparer = new AnimalSizeComparator();
            MyHelper myHelper = new MyHelper();
            (animalComparer);
            (); 

It can be seen that in the method, the actual parameters of the base class interface type can be passed in when calling the method.

Summary: In the scenario of this article, the derived class interface replaces the parent class interface, which is called covariance; the parent class interface replaces the derived class interface, which is called inverter.

The above is the entire content of this article. I hope that the content of this article has certain reference value for your study or work. Thank you for your support. If you want to know more about it, please see the following links