Objective
Work for a year, usually also like to read books, stroll the garden; but when it comes to blogging, there really isn't, after all, just one word: lazy! Now want to get rid of this "problem", I hope that the usual work to learn the knowledge and encountered problems recorded, one can comb their own ideas, deepen understanding, second, can learn from more friends and share; third, can exercise their own writing level;
Usually occasionally encounter a few small problems, many times are checked to remember, or simply write notes, at that time to understand the past, did not form a document, and so on a period of time and encountered the same problems, but also to re-check to understand, very troublesome. I hope that these things will be written in the future, although it may be a small problem, but also as a note record. Some of the concepts, syntax, or specifications of C # are documented in "C # notes." Because not to learn while learning to remember, so there is no certain time and learning order, but usually encountered the need to feel, on record.
First, encounter problems
Work is based on. net3.5 development, the actual process encountered a problem. Suppose we have a base class, a Derived class, and Derived inherits base. As follows:
Class Base { } class Derived:base { }
when I use ienumerable<base> as a parameter,list<derived> as an argument, I find the compilation error! it is normal for the parent class to pass the subclass as a formal parameter, but the compilation does not pass in the generic type.
II. Inquiry Questions
Usually we have a principle in the design parameters and return values, the parameters should be as "Pan", the return value should be as "thin" as possible. Generic, refers to the interface or the parent class as parameters, so that you can receive more parameter types, thin, refers to the return of the specific type, which can better illustrate the role of the method.
As an example:
string[] STRs = new string[] {"Hello", "word"}; The disadvantage is that the array will not be able to pass, but also to call the ToList () static void Test_1 (list<string> List) { } //correct practice, Should be used ienumerable<t> static void test_2 (ienumerable<string> list) { }
As can be seen, the "Pan" of the parameters provides greater flexibility.
Then go on to the topic: resistance to change and co-change. It should be stated that the resistance and covariance are supported at the beginning of 4.0. Suppose there is a method that requires a derived set as a parameter, then based on the above principles, we will design this:
static void Testin (Ienumerable<base> bases) { }
Then we call to the following, in 3.5, we will find that the compilation does not pass, prompting the list<derived> can not be converted to ienumerable<base>.
list<derived> listin = new list<derived> (); Testin (Listin);
With the same code, we got 4.0 and found the build passed. Comparing the IEnumerable generic interface, we found that 4.0 is defined as:
Public interface Ienumerable<out t>: IEnumerable
Find out more out keyword, this is covariant. MSDN's interpretation of type parameters is:out T The type of object to enumerate. The type parameter is covariant. That is, you can use the specified type or a higher-derived type.
We can understand the covariance in this way, the type of the parameter is covariant, and the parent class is substituted for the subclass, which is the subclass when the parent class is used.
After understanding the covariance, the anti-change is good to understand. The return value of the function is immutable, and the subclass is substituted with the parent class, which is the parent class when the subclass is used. In the case of non-generics, we can receive the return value of the method in this way:
Object obj = Test_3 (); static string Test_3 () { return "Hello World"; }
Of course, we think that such calls should also be possible:
ienumerable<base> listout = Testout (); Static ienumerable<derived> Testout () { return new list<derived> (); }
Under 3.5, this will also compile the error. 4.0 is no problem.
Iii. Summary
The concept of covariant and anti-change in fact we often encounter ( parameter covariance, return value resistance ), and we will be accustomed to this design. However, for generics,. NET is 4.0 to provide such support, which provides greater flexibility for generic use.
OK, we don't really need to understand conceptual things, we know the principles and how to use them. The above is my personal understanding, if a friend wants a deeper understanding, you can see MSDN.
C # note 1-anti-change and covariance