157 suggestions for writing high-quality code to improve C # programs [covariant and inverter]

Source: Internet
Author: User
Tags class manager

Preface

This article has been updated to http://www.cnblogs.com/aehyok/p/3624579.html. This article mainly records the following content:

Recommendation 42: use generic parameters to be compatible with the non-variability of generic Interfaces

Suggestion 43. Make the generic parameters in the interface support covariant

Suggestion 44. Understand the covariant in the delegate

Recommended 45. Specify covariant for generic parameters

Recommendation 42: use generic parameters to be compatible with the non-variability of generic Interfaces

To make the return value type return a type that is more derived from the declared type, it is "covariant ". Covariant is not a new technology. In the past coding, we were unconsciously using covariant. The following code is an example of unconsciously Applying covariant:

Class Employee {public string Name {get; set;} class Programmer: Employee {} class Program {public Employee GetAEmployee (string name) {Console. writeLine ("I am an employee:" + name); return new Programmer () {Name = name };} static void Main (string [] args ){}}

Programmer is a subclass of Employee, so a Programmer object is also an Employee object. The GetAEmployee method returns a Programmer object, which is equivalent to returning an Employee object. In versions earlier than FCL4.0, covariant is a natural application, so we are likely to write such code:

    class Employee    {        public string Name { get; set; }    }    class Programmer : Employee    {             }    interface ISalary<T>    {        void Pay();    }    class BaseSalaryCounter<T> : ISalary<T>    {        public void Pay()        {            Console.WriteLine("Pay base salary");        }    }

Next, let's take a look at the calls in the Main function:

    class Program    {        static void Main(string[] args)        {            ISalary<Programmer> s = new BaseSalaryCounter<Programmer>();            PrintSalary(s);        }        static void PrintSalary(ISalary<Employee> s)        {            s.Pay();        }    }

At first glance, the problem should not be big, but the compiler has encountered an error.

The compiler checks the interface and delegate type parameters very strictly, unless the keyword out is specially stated (this will be elaborated in the next suggestion), otherwise this code will only fail to compile, to enable PrintSalary to meet the requirements, we can use generic parameters:

        static void Main(string[] args)        {            ISalary<Programmer> s = new BaseSalaryCounter<Programmer>();            PrintSalary(s);        }        static void PrintSalary<T>(ISalary<T> s)        {            s.Pay();        }

Some people may note that at the beginning of this suggestion, "covariant" is for the return value, but the example does not reflect the concept of "return value. In fact, as long as a generic type parameter is not used as an input parameter of a method in an interface declaration, we can regard it as a "Return Value" type. Therefore, this mode meets the definition of "covariant" in this suggestion. However, as long as T is used as the input parameter, the definition of "covariant" is not satisfied.

 

Suggestion 43. Make the generic parameters in the interface support covariant

In addition to using generic parameters mentioned in recommendation 42 to be compatible with the non-variability of generic interfaces, an out keyword is added to the generic declaration in the interface to support covariant, as follows:

namespace ConsoleApplication10{    class Employee    {        public string Name { get; set; }    }    class Programmer : Employee    {             }    interface ISalary< out T>    {        void Pay();    }    class BaseSalaryCounter<T> : ISalary<T>    {        public void Pay()        {            Console.WriteLine("Pay base salary");        }    }    class Program    {        static void Main(string[] args)        {            ISalary<Programmer> s = new BaseSalaryCounter<Programmer>();            PrintSalary(s);        }        static void PrintSalary(ISalary<Employee> s)        {            s.Pay();        }    }}

The out keyword is a new feature added in FCL4.0. It can be used in generic interfaces and delegation to enable type parameters to support covariance. Through covariant, you can use a parameter that is larger than the declared parameter derivation type. Through the above example, we should be able to understand this application.

FCL4.0 modifies multiple interfaces to support covariant operations, such as IEnumerable <out T>, IEnumerator <out T>, and IQueryable <out T>. Because IEnumerable <out T> currently supports covariant, the code above can run well in FCL4.0.

In our own code, if you want to write a generic interface, we recommend that you add the out keyword unless it is determined that the generic parameters in this interface do not involve variants. The covariant increases the scope of use of the interface and has almost no side effects.

Suggestion 44. Understand the covariant in the delegate

The generic variables in the delegate are naturally partially covariant. Why is it "partially supports covariant? Let's take a look at the following example:

Class Employee {public string Name {get; set ;}} class Manager: Employee {} class Program {public delegate T GetEmployeeHandler <T> (string name ); static void Main (string [] args) {GetEmployeeHandler <Employee> getAEmployee = GetAManager; Employee e = getAEmployee ("Mike"); Console. readLine ();} static Manager GetAManager (string name) {Console. writeLine ("I Am a Manager:" + name); return new Manager () {Name = name};} static Employee GetAEmployee (string name) {Console. writeLine ("I am an Employee:" + name); return new Employee () {Name = name };}}

In the above text, the GetAManager method returns a Manager, but in use, it is actually assigned a value to a delegate variable with the generic parameter "Employee. We may think that generic variables in the delegate do not need the out keyword any more. This is a wrong understanding. An error is reported during compilation because of the following conditions:

To compile the above Code, you also need to specify the out keyword for the generic parameter in the delegate:

public delegate T GetEmployeeHandler< out T>(string name);

Unless this delegate statement is certainly not used for variability, specifying the out keyword for the generic parameter in the delegate will expand the application of the Delegate. We recommend that you always use this keyword in actual coding work, in fact, some of the delegation Statements in FCL4.0 have used the out keyword to change the delegation Support Association, as we often use:

public delegate TResult Func<out TResult>();

Recommended 45. Specify covariant for generic parameters

The parameter of a method can be a base class of the parameter type of a delegate or generic interface. In FCL4.0, the commonly used proxies that support inverters include:

Func<in T,out TResult>Predicate<in T>

Common generic interfaces include:

ICompare<in T>

The following example demonstrates the benefits of specifying an inverter for generic parameters:

Public interface IMyComparable <in T> {int Compare (T other);} public class Employee: IMyComparable <Employee> {public string Name {get; set ;} public int Compare (Employee other) {return Name. compareTo (other. name) ;}} public class Programmer: Employee, IMyComparable <Programmer> {public int Compare (Programmer other) {return Name. compareTo (other. name) ;}} public class Manager: Employee {} class Program {static void Main (string [] args) {Programmer p = new Programmer () {Name = "Mike "}; manager m = new Manager () {Name = "aehyok"}; Test (p, m);} static void Test <T> (IMyComparable <T> t1, T t2) {// omitted }}

In the above example, if you do not specify the in keyword for the generic parameter T of the interface IMyComparable, the Test (p, m) Compilation error will occur. Due to the introduction of the inverse nature of the interface, the Test method supports more application scenarios. Always pay attention to this in the actual encoding of FCL4.0 and later versions.

 

Tips for English

1. Then, please give me a new reservation. -- so, please help me reset the reservation.

2. Sorry, this flight is full. -- Sorry, this flight is fully occupied.

3. What is the possibility of my gettinga seat if I wait? -- If I wait here, what is the chance of an organic place?

4. When will the next flight to Los Angeles leave? -- When will the next flight to the plane take off?

5. The day after tomorrow, Friday. -- The day after tomorrow, Friday.

6. That will be fine. What's the flight number and departure time? -- Great. Can you tell me the flight number and departure time?

7. What is the fare? -- What is the cost?

Author: aehyok

Source: http://www.cnblogs.com/aehyok/

Thank you for reading this article. If you are interested in the content described in my blog, please make a suggestion. Thank you for your support:-O.

 

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.