Je me demande pourquoi La combinaison des deux fonctionnalités ne fonctionne pas cependant ... p> merci pour votre aide!
Sebastian p> p> ienumerable
iEnumerable
ienumerable code> est l'une des rares interfaces qui prend en charge la covariance ...
int code> semble être un sous-type approprié de
objet code> li>
ul>
4 Réponses :
Le problème est que Pour attribuer objet code> est un type de référence, pas un type de valeur. La seule raison pour laquelle vous pouvez attribuer un
int code> à une variable de type
objet code> est la boxe. P>
Liste
iEnumerable
Merci pour cette explication facile. Nous avons donc des variables d'objet et d'int qui peuvent avoir le type d'exécution INT32. Cependant, je pense qu'il y a une faille de conception en C #, lorsque la boxe implicite est faite dans un cas et non dans l'autre ... Une fois et se comporte comme un sous-type, la prochaine fois que ce n'est pas le cas. Donc, ce n'est pas un sous-type. Merci...
@Sebastiangregor: le moyen le plus simple de penser que les choses consiste à reconnaître que system.int32 code> décrit un type d'objet de tas qui dérive à partir de
ValueType code> qui dérive à partir de
objet < / Code>, et décrit également un type d'emplacement de stockage implicitement convertible au type d'objet HEP-HEP et explicitement convertible de celui-ci.
Les types de valeur ne sont pas des sous-types de LSP d'objet jusqu'à ce qu'ils soient en boîte.
variance ne fonctionne pas avec des types de valeur. Du tout. P>
démonstration que fonctionne: p> ne fonctionne pas (substituabilité violée): p> retournets VRAI: P> int code> n'est pas un em> (sous-type dans le sens de la LSP) de
objet code >:: p>
int y = new int();
object a = y;
object b = y;
return ReferenceEquals(a, b);
Je n'irais pas aussi loin que votre première phrase. Comment int code> pas un sous-type de
objet code>? Il remplace les méthodes virtuelles
gethascode code> et
tostring code> et hérités
gettype code> ... et peut être transmis à n'importe quelle méthode qui accepte un objet
< / code> paramètre ...
@Dan: Vous ne pensez pas à passer un int code> à une méthode avec un objet
objet code> Paramètre provoque la boxe? Non, un
int code> n'est pas un sous-type de
objet code>. Il n'a pas de table V à moins que et jusqu'à ce qu'il soit en boîte.
@Ben Voigt: Je n'ai rien dit de la boxe. J'ai dit int code> est un sous-type de
objet code>. Supposons que j'ai cette méthode:
Format de chaîne
format
x code> pour être en boîte? Non, je pense que vous traitez ces concepts comme plus étroitement liés qu'ils ne le sont.
@Dan: Cela ne provoquera pas de boxe, uniquement parce que les génériques sont spécialisés pour les types de valeur. Il n'y a pas de polymorphisme ici, le JIT génère un code de machine spécialement pour format
int.tostring (& arg) code>. D'autre part, considérez
nettoyage vide
Nettoyage
x code> pour être en boîte.
@Dan, int n'est pas un sous-type d'objet; Regardez la documentation MSDN: msdn.microsoft.com/en-us/ bibliothèque / system.int32.aspx int32 est une structure. Les génériques sont écrits de manière à gérer les types de valeur et les types de référence séparément, et vous pouvez donc utiliser une méthode générique pour contourner la boxe utilisée pour que vous puissiez passer un type de valeur à une méthode en attente d'un type de référence.
@Chris: MSDN ne montre pas system.Object code> comme type de base même de types qui héritent directement de cela, de sorte que cela ne prouve pas beaucoup.
@Ben, @chris: Dan est correct. Tous les types hériter de objet code>. La spécification de langue est absolument claire à ce sujet: "C # fournit un" système de type unifié ". Tous types - y compris les types de valeur - dérive du type
objet code>. Il est possible d'appeler objet Méthodes sur n'importe quelle valeur, voire des valeurs des types "primitifs" tels que
int code>. " i> ( de la section 8.2.4 de la spécification de la CCMA C # )
@Ben: Je n'aurais pas dû même donner cet exemple; Mon point réel est que boxing i> est un problème complètement séparé de l'héritage. Qu'est-ce que cela signifie d'être un sous-type, vraiment? Cela signifie que vous hériter des méthodes publiques et protégées et vous pouvez être transmis à n'importe quelle fonction qui attend votre type de base. Considérez ceci: Définissez votre propre struct code> et incluez cette méthode:
Clone d'objet public () {Retour MembeClone (); } code> Comment supposez-vous avoir accès à ce membre Protégé i> membre de
objet code>? C'est parce que votre
struct code> est un sous-type!
@Lukeh, @Dan: Un boxé int code> est un sous-type d'objet, comme je l'ai dit dans ma réponse. Seuls case
int code> S peut être transmis à des fonctions qui acceptent
objet code> (ou stocké dans n'importe quelle variable de type
objet code>, qu'il s'agisse d'un paramètre ou non) . Et non, la réutilisation du code n'implique pas le sous-traitant. Il y a aussi une composition. L'accessibilité protégée est liée à l'héritage, mais veuillez noter que si vous appelez
membrewiseclone () code> à l'intérieur d'une valeur de valeur, la boxe se produit. Toute instance d'un type de valeur doit d'abord être en boîte avant de pouvoir être traitée comme type
objet code>.
@Dan: Puis-je souligner qu'un sous-type approprié doit contenir un sous-ovoir du type de base? Un int code> ne contient pas les champs d'une instance de
objet code>. Un boxé
int code>, d'autre part, fait.
@Ben: Je ne conteste pas votre description des mécanismes sous-jacents, mais il n'y a pas de tort du fait qu'un int code>, boxé ou non incorporé, dérive de
objet code>. C'est tout le point d'avoir un "système de type unifié", n'est-ce pas?
@Ben voigt: où i> obtenez-vous cette notion que "afin d'accéder à certains membres de x code>, type
y code> doit être en boîte" quelque chose d'une manière ou d'une autre signifie "
y code> n'est donc pas un sous-type de
x code>"? En outre, quels champs de
objet code>? Il n'y en a pas.
@Lukeh: Il s'agit d'un type dérivé aux fins de l'accès aux membres protégés. Ce n'est pas un type dérivé dans aucun autre sens. Ne contient pas d'objet code> code> subrobject. Ne peut pas être utilisé dans une instruction code> verrouillage code>, même si objet code> peut. Viole la LSP plus de façons que je ne peux compter.
@DAN: OUI objet code> a des champs. La tablette. Un moniteur. Juste parce qu'ils ne sont pas exposés à C # ne veulent pas dire qu'ils ne sont pas là. Un
int code> prend moins d'espace qu'un objet
code>, par conséquent un
int code> ne peut pas être clairement un objet code> dans le sens où le sous-typage nécessite. Une fois encadré, cependant, il contient une sous-observation de type
objet code>.
@Ben VoigT: En fin de compte, je pense que le problème avec ce que vous dites est que vous parlez de instances i> de types comme si elles sont i> types. Dire "Un boxé int code> est un sous-type de
objet code>" n'est pas correct; "Un boxé
int code>" n'est pas un type i> du tout; C'est un objet i>. Il n'y a pas de type comme un type parfois i> un sous-type d'un autre type. est i> ou ce n'est pas le cas. Tous les types i> .NET sont des sous-types de
objet code>.
@Ben: la boxe et le non-coffre sont les mécanismes permettant un "système de type unifié"; L'existence de ces mécanismes ne prouve pas d'une manière ou d'une autre que les types de valeur ne sont pas des objets. La spécification est encore absolument claire à ce sujet: "Chaque type en C # directement ou indirectement provient de l'objet code> de type de classe et objet code> est la classe de base ultime de tous types. Les valeurs de types de référence sont traitées comme des objets simplement en affichant les valeurs comme type
objet code>. Les valeurs des types de valeur sont traitées comme des objets en effectuant des opérations de la boxe et de la transbording. " I> (de Section 11 de la CECMA SPEC)
@Dan: Un int code> a une disposition de mémoire différente d'un
Int code>. Ils ont des types différents. Les instructions
BOX CODE> et
UNBOX CODE> doivent convertir entre eux (à l'exception des cas spéciaux au sein des génériques). Vous avez raison pour que une instance n'est pas un type, j'aurais dû dire "un boxé
int code> 's i> est un sous-type de
objet code>" le C # Compilateur confond le problème en générant le
Box code> et
instructions code> instructions en silence.
@Lukeh: Cela soutient ma réclamation assez bien. Les valeurs des types de valeurs deviennent des objets quand ils sont en boîte. Ils ne sont pas autrement.
@Ben: la citation ne dit pas ça. Cet argument entier est de Nitpicking sur la sémantique. Vous parlez des mécanismes de mise en œuvre; Dan et moi parlons de la vue d'ensemble conceptuel. La citation dit explicitement que " objet code> est la classe de base ultime de Tous B> Types" i> [met l'accent sur la mine].
@Lukeh: Alors? Dans le monde .NET, lorsque les types de valeur sont impliqués (ils constituent un cas particulier tout au long de l'exécution), la dérivation ne signifie pas le sous-typing. Le LSP est un test très simple pour le sous-typing et les types de valeur échouent de manière misérablement.
@Ben, @Lukeh: Je dois dire, je pense que nous sommes tous (Ben et moi surtout) simplement parler les uns des autres. Personne ne dit que les autres ne savaient pas déjà. Nous faisons simplement des définitions différentes de ce que signifie être un sous-type. Personnellement, je privilégie Luke et ma position parce que cela accepte la définition utilisée par la spécification. Ben est essentiellement en désaccord avec la spécification basée sur une manière différente de définir le terme. Alors, Ben, je n'aime pas votre définition; Mais au moins, je comprends ce que vous dites (et je pense que vous comprenez ce que je dis).
@BEN: Oui, les types de valeur sont indéniablement spéciaux. La boxe et le décoffrage sont des mécanismes qui (principalement) activer le LSP avec des types de valeur. @Dan: absolument d'accord.
@Dan: Ici, j'ai fait un léger changement à ma réponse pour que je ne parle pas que je ne parle pas de la "spécification C # indique objet code> est une classe de base" sens du terme Sous-type i>. Chose est que le "sous-type" basé sur les spécifications est inutile dans ce contexte. Être une classe dérivée selon la spécification n'est pas ce qui rend les travaux de variance d'interface. Être un SSP-SUBTYPE est ce qui rend le travail de variance d'interface.
Ok, maintenant je pourquoi savoir pourquoi quelqu'un a changé de vote à un bowvote. Je peux démontrer que int code> n'est pas un lsp-sous-type de
objet code> assez facilement.
Le LSP est pas i> un test simple pour le sous-typing. Si vous pensez que c'est, alors par tous signifie, postez un court algorithme en C # pour déterminer si les deux types de deux types le satisfont.
@GABE: Défaucher par contre-exemple est simple. La question est un contre-exemple, ma réponse contient deux autres.
@GABE: Vous ne pouvez pas argumenter ce point à Ben, car il utilise le LSP dans sa définition b> de ce que le mot sous-type i> signifie. @Ben: Gabe n'a pas fait de réclamation que vous pouvez réfuter. Il (avec moi et Luke) dit que le sous-typing n'est pas défini par LSP. Votre «contre-exemple» est basé sur la prémisse opposée.
@Dan: Tu as raison, mais je ne voulais pas dire que l'utilisation du LSP n'est pas i> un test. Je voulais dire que le LSP n'est pas simple i>. Il est à la fois indécrivible et subjectif, il ne tombe donc pas sous ma définition de «simple». Peut-être que la définition de Ben est différente, cependant.
@Gabe: Droite, c'est un bon point. @Ben: Il me semble que si vous prenez votre critère pour la sous-tension à l'extrême, vous pourriez "réfuter" que n'importe quel type i> est un sous-type d'un autre. Ecrivez une méthode triviale qui accepte un objet code> et jette une exception si l'objet passé a un type plus spécifique. Maintenant, le comportement de votre programme est différent selon que vous passez dans un objet
objet code> ou une chaîne
code>; et le LSP est violé. Comment est-ce différent de vos exemples?
@Gabe: prouvant qu'une relation de sous-typographie LSP est pas simple. Prouvant qu'il ne tient pas, est facile. Un contre-exemple suffit. Ceci est typique des hypothèses scientifiques. @DAN: Vous faites un bon point que gettype code> dans n'importe quel sous-type aura un comportement différent. Devrions-nous convenir que le contrat à des fins de LSP doit être "
gettype () code> renvoie une instance NULL code> NULL code> de
system.type code>" plutôt que "
gettype () code> retour
typeof (objet) code>? Mais cela tente explicitement de détecter différents types, alors que je pense que mes exemples couvrent un comportement légitimement différent, ce ne sont pas des hommes de paille.
Aucun de vos exemples n'est des violations appropriées car vous ne les avez pas indiqués correctement. Le premier devrait comparer objet x = nouvel objet (); verrouillage (x) {...} code> contre
objet x = nouveau int (); verrouillage (x) {...} code>.
@Jason: le fait que objet x = nouveau int (); code> prend en charge les opérations que
int x = nouveau int (); code> ne prouve pas que
int code> et "boxé
int code>" sont différents types. Qui est mon point.
@BEN VOIGT: Il vous manque le point de ma déclaration qui est effectivement que vous avez mal compris la déclaration du LSP.
@Jason: Je comprends que tu dis ça. Mais tu as tort. Vous ne pouvez pas utiliser de boîte intégrée pour tester la substituabilité de int code> lui-même. La question ne concerne pas une liste
list
Liste
Je suggérerais de réécrire votre exemple d'utilisation des paramètres de type générique: Test BOOL
objet code>, même si un Boxed
int code> est.
Chaque type de valeur dans .NET a un type d'objet correspondant ("Boxed"). Les types de valeur non en boîte sont effectivement en dehors de la hiérarchie de type d'objet, mais le compilateur effectuera un élargissement du type de valeur au type de classe en boîte. Il serait utile d'avoir une "classe" boxée
Oui. Je pense aussi qu'un tel type aiderait beaucoup. int i = 4; objet x = i; Console.writeine (x.getType ()); devrait alors retourner en boîte
@Sebastian Gregor: Je ne suis pas sûr que je ne suis pas sûr de la meilleure sémantique pour GetType, mais il y a eu des occasions lorsque je me suis retrouvé en créant une classe détenant un type de valeur unique lorsque cela aurait été plus pratique d'avoir un type de boîte qui pourrait avoir été utilisé implicitement comme type de valeur. Pour ses propres types, il est parfois utile de déclarer faille
... soit une foo boxe ou non incorporée comme paramètre. Curieusement, il est possible d'accéder aux membres d'interface explicites d'une structure sans boxe ni d'autres allocations de tas, mais je ne peux pas comprendre une manière vraiment propre.
La réponse simpliste est que ce n'est que l'un des bizarreries de la manière dont la variance est mise en œuvre dans C # et le CLR. P>
de "Covariant et Contravariance en génériques" : P >
variance s'applique uniquement à la référence les types; Si vous spécifiez un type de valeur pour un paramètre de type variant, ce type Le paramètre est invariant pour le type construit résultant. P> blockQuote>
Seriez-vous savoir pourquoi?