9
votes

Règles de variance en C #

Le exacte Les règles de validité de la variance sont un peu vagues et non spécifiques. Je vais énumérer les règles de ce qui rend un type valide-covariant et joignez des questions et des annotations personnelles à chacune de ces règles.

Un type est covariant valide s'il est:

1) un type de pointeur ou un type non générique.

Les pointeurs et les types non génériques ne sont pas une variante dans C #, à l'exception des tableaux et des délégués non génériques. Les classes génériques, les structures et les énumérums sont invariants. Suis-je raison ici?

2) Un type de tableau T [] où T est valide covarienne.

Cela signifie que si le type d'élément t d'un tableau t [] est covariant (type d'élément de référence ou tableau), puis le tableau est covariant, et si Le type d'élément est invariant (type de valeur), puis le type de tableau est invariant. Les tableaux ne peuvent pas être contravariat en C #. Suis-je raison ici?

3) Un type de paramètre de type générique, s'il n'a pas été déclaré comme contravare.

Nous disons normalement qu'un type générique est une variante sur un type de paramètre, mais pour un type de paramètre à variante est propre. Est-ce une autre forme courte pour dire cela? Par exemple, le type générique t est covariant sur d (valide de manière covarienne), par conséquent, nous pouvons dire que le paramètre type d est valide de manière covarienne? Ai-je raison?

4) Une classe construite, une structure, un énumération, une interface ou un délégué de type x pourrait être valide de manière coovarienne. Pour déterminer si c'est le cas, nous examinons chaque argument de type différemment, selon que le paramètre de type correspondant a été déclaré comme covariant (OUT), Contraveurt (IN) ou invariant (ni invariant (ni). (Bien sûr, les paramètres de type générique des classes et des structures ne seront jamais déclarés «out» ou «dans»; ils seront toujours invariants.) Si le paramètre de type ITH a été déclaré comme covariant, alors TI doit être valide de manière coovarienne. Si cela a été déclaré comme contrevenue, TI doit être valable contrefaviertly. Si cela a été déclaré invariant, TI doit être valide invariant.

Cette dernière règle, de haut en bas, est totalement ambiguë.

Parlez-nous d'une variance de type générique sur tous ses paramètres de type IN / OUT / invariant? Par définition, un type générique peut être covariant / Contraveurt / invariant sur un paramètre de type à la fois. Pour être covariant ou invariant, dans ce cas, sur tous les paramètres de type de type à la fois ne contiennent aucune signification. Qu'est-ce que cela pourrait signifier?

aller de l'avant. Pour déterminer si le type générique est valide de manière covarienne, nous examinons ses arguments de type (PAS TYPE PARAMERS) . Donc, si le paramètre de type correspondant est Covariant / Contravariant / invariant, l'argument de type est valide de manière coovarienne / contrevarargie / invariante respectivement ...

J'ai besoin que cette règle soit expliquée plus en profondeur.


EDIT: Merci Eric. Grandement apprécié!

Je comprends parfaitement ce que signifie une moyenne covariante / invariante valide / invariante. Un type est valide coviantliant, si ce n'est certainement pas contrevenue, ce qui signifie que cela peut être invariant. Parfaitement bien!

Pour la 4ème règle, vous suivez la procédure de détermination de la manière de déterminer si un type générique construit est valide de manière coovarienne, telle que définie dans la règle. Mais comment déterminez-vous si un argument de type déclaré comme Covariant (OUT) est valide de manière covarienne?

Par exemple, dans la Interface construite fermée I {} de l'interface générique i {...} , ne devrait pas le fait que l'argument de type objet est déclaré comme un paramètre Covariant Type Paramètre (Out U) dans la déclaration d'interface générique signifie que l'objet d'argument de type est covariant? Je pense que ça devrait. Cuz c'est la définition même d'être covariant.

aussi, la deuxième règle:

2) Un type de tableau T [] où T est valide covarienne.

Qu'est-ce que le type d'élément de tableau t étant valide covariant moyenne? Voulez-vous dire que le type d'élément étant un type type (invariant dans ce cas) ou un type de référence (Covariant dans ce cas)?

cuz la projection t t [] est seulement une variante si t est un type de référence.


2 commentaires

Ce n'est vraiment pas comme si Eric Lippert soit vague ou ambiguë. Pour que je puisse attendre qu'il pèse avant de tester la profondeur de cette petite flaque d'eau.


Cet article est différent Gjeltema. Dans mon précédent publipostage sur la variance, ma compréhension de la variance et ses terminologies associées à court terme ont été clarifiées.


3 Réponses :


4
votes

Non, vos annotations sont gâchées.

Cet article est vraiment difficile à comprendre, en partie parce que "Valide Covariandly" n'a rien du tout à faire avec la covariance. Eric fait remarquer cela, mais cela signifie pour chaque phrase que vous devez "impressionner" le sens naturel, puis penser en termes de ces définitions étranges pour "Valable Covariandly", "Valid Confirmythly" et "Valable invariant".

Je vous recommande vivement de lire à la place du principe de substitution de Liskov, puis de penser à la substituabilité. La covariance, la contrevenance et l'invariance ont des définitions très simples lorsqu'elles ont examiné le point de vue de la LSP.

Ensuite, vous remarquerez peut-être que les règles C # au moment de la compilation ne correspondent pas exactement au LSP (malheureusement - et il s'agit principalement d'une erreur faite en Java et de copie en C # pour aider les programmeurs de cour Java). D'autre part, au moment de l'exécution, les règles de la LSP doivent être suivies, donc si vous commencez avec ceux-ci, vous écrirez du code qui compile et exécute correctement, ce qui, je pense, est une entreprise plus utile que Apprendre les règles de langue C # (sauf si vous écrivez un compilateur C #).


0 commentaires

13
votes

Vous avez raison que la dernière règle est la plus difficile à comprendre, mais je vous assure que ce n'est pas ambigu.

Un exemple ou deux aidera. Considérons cette déclaration de type: P>

interface IEnumerable<out W> { ... }
interface I<in T, out U, V> 
{
    IEnumerable<T> M();
}


1 commentaires

Merci Eric. Pouvez-vous répondre aux deux nouvelles petites questions ajoutées à la fin de mon poste d'origine?



4
votes

Comment déterminez-vous si un argument de type déclaré comme Covariant (OUT) est valide de manière covarienne?

Lire la règle 3.

dans l'interface construite i {string, objet int> de l'interface générique i , ne devrait pas le fait même que l'argument de type objet est déclaré comme un paramètre de type covariant U dans la déclaration d'interface générique signifie que l'argument de type objet < / code> est covariant?

Premièrement, vous utilisez "Covariant" où vous voulez dire "Covariant valide". N'oubliez pas que ce sont des choses différentes.

Deuxièmement, passons à nouveau. Est objet covariant valide? Oui, par règle 1. est i covariély valide? Oui, par règle 3, qui indique que:

  • L'argument de type correspondant à T doit être contravériaire valide.
  • L'argument de type correspondant à u doit être valide de manière covarienne.
  • L'argument de type correspondant à V doit être à la fois.

    Étant donné que les trois conditions sont remplies, i est valide de manière covarienne.

    in "Un type de tableau T [] où T est valide covariély" Qu'est-ce que l'élément de tableau T-sorte T étant valide de manière coovarienne?

    Je ne comprends pas la question. Nous sommes Définir ce que signifie "covariant valide". La règle 2 fait partie de la définition de "Covariatly valide".

    comme exemple, est objet [] covariély valide? Oui, parce que objet est valide de manière covarienne. Si nous avions: xxx

    est t [] covariant valide? Oui, car t est valide de manière covarienne.

    si nous avions xxx

    est t [] Covariant valide? Non. Pour qu'un type de matrice soit covariant, son type d'élément doit être valide de manière covarienne, mais t n'est pas.


1 commentaires

J'ai compris! J'étais vraiment inconsciemment confondant les différents termes les uns avec les autres. Eric apprécié.