What you don't know about C # covariant and Inverter

Source: Internet
Author: User

The original address is unknown. Sorry.

The msdn explanation is as follows:
"Covariant" refers to a type with a greater degree of derivation than the original specified derivative type.
* A * @ 'd + Y. C "G * w" invert "refers to a type that can be derived to a smaller extent.
The explanation is correct. This is generally the case, but it is not straightforward enough.
1 L ~) F3 E (I6 | straightforward understanding:
"Covariant"-> "harmonious variant"-> "natural variant"-> string-> Object: covariant.
"Invert"-> "reverse constant change"-> "abnormal change"-> Object-> string inversion.
7 S7 T1 H, X #] The above is my personal understanding of covariant and inverter. Compared with remembering words such as derivation, type, original designation, bigger, and smaller, I personally think it is easier.
The following is a joke:
Every day of a week should read as follows:
& J3 V-R7 U. U) O Monday = busy day;
9 C8 f * N $ Y & L3 X &} 8 S4 P Tuesday = survival Day;
) U! V, M/D4 H Wednesday = Not dead day;
Thursday = day of death;
3 Q: G & B f (u # V9 T N Friday = fulai day;
: L7 J, f * x/e Saturday = free and easy day;
5 D! Y % u: c-e'm Sunday = injury day
"\)'! P % Z1 C s' | 8 _! C To demonstrate the differences between covariant and inverter, create the console program castudy and manually add two classes:

Because it is a demonstration, it is all empty classes, but remember that dog inherits from animal. So changing dog to animal is a harmonious change (covariant), and changing animal to dog is an abnormal change (inverter)
1 K4 | % L & D9 \ * C/f. _ (input in main function:
: W7 C6 d F; S +
) [$ [2 Y8 R; q) R + C5 | because dog inherits from animal, animal aanimal = adog; adog is implicitly converted to animal. But list <dog> does not inherit list <animal>, so the following prompt appears:

8 s 'i0 J3? + G % | * Q6 Z use the following code if you want to convert:

  • List <animal> lstanimal = lstdogs. Select (D => (animal) d). tolist ();
    7] "C + G % '2 T7 P (K $

We can see how complicated it is to change an lstdogs to an lstanimal.
+ G2 J; \) Q & {; | * V * j. For this reason, Microsoft has added two keywords: Out, In. Their msdn explanation is as follows:


5 H # H; E & Z8 U-'% x & Q. The English version of the B covariant is "covariant", and the English version of the inverter is "contravariant"
3x0 {7 W $ c j (B: Y1 s why does Microsoft choose "out" and "in" as features rather than them?
6 J * M2 v 'm7 B my personal understanding: because the English language of the covariant and inverter is too complex, it does not reflect the differences between the covariant and the inverter, however, out and in are straightforward. Out: output (as result), in: input (as parameter ). Therefore, if a generic parameter is marked as out, it indicates that it is used for output and can only be returned as a result. If a generic parameter is marked as in, it indicates that it is used for input, that is, it can only be used as a parameter. Currently, the out and in keywords can only be used in interfaces and delegation. Microsoft uses the out and in Mark interfaces and delegation as follows:


First look at the first ienumerable <t>

! I 'h4 H2 H7 o "t is the same as that mentioned at the beginning. t is marked with out, So t represents the output, that is, it can only be returned as a result.
8 x: Q % O: d % E & F9 X # X8 u
7 D7 _ 0 y9 ^ 1 W! \; K

    Public static void main ()

  • {
    Dog adog = new dog ();
  • Animal aanimal = adog;
    + V/L H1 _ & X6 zlist <dog> lstdogs = new list <dog> ();
  • // List <animal> lstanimal = lstdogs;
    & W $ C -? 7 A-D + rlist <animal> lstanimal = lstdogs. Select (D => (animal) d). tolist ();
  • Ienumerable <dog> somedogs = new list <dog> ();
    + {, H6 S: Z2 ^; s "W" A3 U $ K: l % m3 uienumerable <animal> someanimals = somedogs;
  • }

Because t can only return results, t will not be modified, and the compiler can infer that the following statements are valid for forced conversion.
'R5 m' K2 V: P; B "W0? 8 Q3? '^

  • Ienumerable <animal> someanimals = somedogs;

The decompilation code can be checked by the compiler as follows:
(T, D,}/o $ X: z0 o % v 'C
Although the C # compiler has passed the check, the Il does not know whether the covariant and inverter are correct, and it still needs to be forced conversion. Here I see this sentence:

  • Ienumerable <animal> enumerable2 = (ienumerable <animal>) enumerable1;

Can list <animal> lstanim_3 = (list <animal>) lstdogs?
8 N) y2 Y3 h; '% O to answer this question, you need to go back to the CLR via C # section on generics and interfaces. I will not explain it, the answer is no. The above demonstrates the covariant. Next we will demonstrate the inverter. To demonstrate the inverter, you need to find an in-marked interface or delegate. The simplest is:

-X8 X2 P9 T * [, N: Z3 _ add the following to the main function:
9 m3 C # |! C' B
2 T-J5 D-R "e. m"'t & _ $ N * y7 V (x 'a

    Action <animal> actionanimal = new action <animal> (A = >{/ * call an animal */});

  • Action <dog> actiondog = actionanimal;
  • Actiondog (adog );
    4 ^ * T8 Q3 R! X + {

Obviously, actionanimal is called by animals. Because dog is an animal, since animal can be called, dog can also be called.
# U w & H4] 8 Qin keywords: inverter, representing input, representing only usable, not returned value, therefore, the C # compiler can infer that this generic type can only be used based on the in keyword. Therefore, the action <dog> actiondog = actionanimal can be checked by the compiler.
Demonstrate the out keyword again: Add two classes:

"S % S + O. W7 E (^ 7G: [: |; x

    Public interface imylist <out T>

  • {
    T getelement ();
  • }
    Public class mylist <t>: imylist <t>
  • {
    Public t getelement ()
  • {
    2 |) L (k) M8 g * _ 8 C $ H, creturn default (t );
  • }
  • }
    ! S; F4 B! O/] & ~ 'L6 W: d

Because of the out keyword, the following code can be compiled
'Y1 G2 S7 \ 3 a' K

    Imylist <dog> mydogs = new mylist <dog> ();

  • Imylist <animal> myanimals = mydogs;

Modify the preceding two classes:
! T! | # J4 q + x

    Public interface imylist <out T>

  • {
  • T getelement ();
  • Void changet (t );
    }
  • Public class mylist <t>: imylist <t>
    9 T2 y0 r d/H1] % v A4 f {
  • Public t getelement ()
    {
  • Return default (t );
    2 ~! C4 A9} 5 p; Z # X & L "I}
  • Public void changet (T)
    ! Y $ l! F (K! W: p! P0 F $ {
  • // Change t
    2 J % z * j *~ 'S}
  • }
    9 D2 I: T: '. P1 U + G8 g

Compile:
# _ 4 T2 X; R #'5 X, v P z/L7 u
,} 2G. [0 w/g Because t is modified by out, t can only be used as a parameter. Modify two classes as follows:
$ S7 V5 K f: M8 U) S6 [! H0 U % Y

    Public interface imylist <in T>

  • {
    T getelement ();
  • Void changet (t );
    }
  • Public class mylist <t>: imylist <t>
    {
  • Public t getelement ()
    : Z (~ 2 I1 s "G $ I {
  • Return default (t );
    9 A 'i2 Z X4 W "', S: e4 d}
  • Public void changet (T)
    -C1 \ W "'4] + B! A1 Z {
  • // Change t
    }
  • }
    4 V % ~ '_! V'j J5 B (D7 J

This time, the in keyword is used. Compile:

, Y (A5 G6 Q! K "m is marked with the in keyword, so t can only be used and cannot be returned. Finally, modify the code:
, ^. S (@ 8 K % Q:

    Public interface imylist <in T>

  • {
    Void changet (t );
  • }
  • Public class mylist <t>: imylist <t>
  • {
    Public void changet (T)
  • {
    3 A6 I V * P2 L3 d '? // Change t
  • }
  • }
    ) Y/U0 f) G5 U G2 L7 E; e

Compiled successfully, because in represents the inverter, so

: Q-H9] $ I S % Z

    Imylist <animal> myanimals = new mylist <animal> ();

  • Imylist <dog> mydogs = myanimals;
    0 o, V 'w1 Q! \, Z7 V6 Q

Compilation successful !.
% Z8 F (~. V + '1 D: O. y0 Q8 X! G

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.