C # inverter and covariant,

Source: Internet
Author: User

C # inverter and covariant,

This article uses many delegate and Lambda expressions. If you are not familiar with these expressions, please refer to my articles "delegation and anonymous delegation" and "anonymous delegation and Lambda expressions" to help you build a complete knowledge system.

In the process from C #'s birth to its growth, new knowledge points are constantly introduced. Inverter and covariant are not originally created by C # and are subsequently introduced. There are also inverter and covariant in Java. I will write an article on covariant in Java later. If you are interested, please take a look.

Inverter and covariant sounds abstract and advanced, but they are actually very simple. See the following code:

class Person    {    }    class Student : Person    {    }    class Teacher: Person    {    }        class Program    {        static void Main(string[] args)        {            List<Person> plist = new List<Person>();            plist = new List<Student>();            plist = new List<Teacher>();}}

In the above Code, plist = new List <Student> () and plist = new List <Teacher> () generate a compilation error. Although Person is the parent class of Student/Teacher, the List <Person> type is not the parent class of the List <Student/Teacher> type. Therefore, the above assignment statement reports a type conversion failure error.

Such a value assignment operation is not allowed before C #4.0. As to why it is not allowed, type security is the primary factor. See the following sample code:

List<Person> plist = new List<Student>();plist.Add(new Person());plist.Add(new Student());plist.Add(new Teacher());

For example, if List <Person> plist = new List <Student> () allows a value assignment, although the plist type is List <Person> set, however, the actual point is actually the List <Student> set. Plist. Add (new Person (). The Add operation actually calls List <Student>. Add (). The Person type cannot be safely converted to Student, so such a set definition is meaningless, so the above assumptions are not true.

But the situation has changed since C #4.0, not"Something impossible has happened ",But the flexibility of the application has been adjusted. The same program in C #4.0 is still not allowed, but there are exceptions. Starting from C #4.0, special cases are allowed in generic delegation and generic interfaces (in essence, no special changes are allowed, as described later ). Example:

 

Delegate void Work <T> (T item); class Person {public string Name {get; set ;}} class Student: Person {public string Like {get; set ;}} class Teacher: Person {public string Teach {get; set ;}} class Program {static void Main (string [] args) {Work <Person> worker = (p) ==>{ Console. writeLine (p. name) ;}; Work <Student> student_worker = (s) =>{ Console. writeLine (s. like) ;}; student_worker = worker; // compilation error }}

 

Based on the previous theoretical support, student_worker = worker; errors are easy to understand. However, the purpose of our program is to enable woker to act as the Work <Student> function. In the future, student_worker (s) will actually call woker (s ). To meet our needs, we need to implement two procedures:

1. When student_worker (s) is called, woker (s) is actually executed. Therefore, the type of s variable is required to be successfully converted to the parameter type required by woker.

2. the compiler must be informed that the Work <Person> type objects can be assigned to Work <Student> type variables.

 

When condition 1 is called, student_worker (), the compiler prompts that the parameter must be a Student type object, and the object can be converted to a Person type object.

Condition 2 requires adjustments to the Woke delegate definition as follows:

delegate void WorkIn<in T>(T item);

Changing the delegate name to WorkIn is the delegate before and after modification. The key is <in T>. Add the in keyword to mark the type parameter T of the generic delegate and use it only as a parameter of the delegate method. The above program can be compiled and executed successfully.

delegate void WorkIn<in T>(T item);class Program    {        static void Main(string[] args)        {            WorkIn<Person> woker = (p) => { Console.WriteLine(p.Name); };            WorkIn<Student> student_worker = woker;            student_worker(new Student() { Name="tom", Like="C#" });        }    }

In this case, if the required type parameter is a child type and the allowed value is a parent type parameter, it is called an inverter. In C #, You need to mark generic type parameters with in. Although the inverter is called the inverter, it only seems that the parent class object is assigned to the subclass variable in the form, essentially the type conversion of parameters when the method is called. Student s = new Person (), which is not impossible. This is not an inverter error.

If you can convert the above Code into the following form, you can forget the inverter, which is more important than the phenomenon.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.