J'ai le programme C # bref suivant: Ce programme ne compile pas. La dernière ligne provoque l'erreur de compilation suivante: P> ne peut pas convertir implicitement le type 'System.Collections.Generic.List' à 'System.collections.Generic.List'.
Une conversion explicite existe (manquez-vous un casting?) P>
BlockQuote> Donc, j'ai ajouté la distribution: p> Le programme compile correctement, mais échoue au moment de l'exécution. Un Impossible de lancer Objet de type 'System.Collections.Generic.list'1 [System.string]' Pour taper 'System.Collections.Generic.List'1 [System.Object]'. P>
BlockQuote> Soit le casting est illégal et doit être pris par le compilateur, soit il est légal et ne devrait pas jeter une exception au moment de l'exécution. Pourquoi le comportement incohérent? P> Clarification: Je ne demande pas pourquoi le moule échoue. Je comprends pourquoi ce casting est problématique. Je demande pourquoi le moule échoue uniquement à l'exécution em>. P> p>
InvalidCastException code> est soulevé avec le message suivant: P>
5 Réponses :
Vous pouvez le faire par initialisateur de collecte. Les extraits de code ci-dessous fonctionnent pour moi.
listObject.Add(10); // ok string s = listString[0]; // WTF?!!! Due to IList mutability such conversion is meaningless.
Ce qui serait une excellente raison pour que le compilateur empêche la distribution. Cependant, la distribution est autorisée et échoue au moment de l'exécution. Pourquoi l'incohérence ici?
Il n'y a pas d'incohérence, une classe implémentant IList
Une façon de trouver la liste des chaînes à une liste d'objets serait la suivante:
IList<object> objects = listOfStrings.Cast<Object>().ToList();
Notez également que l'ajout d'une chaîne à la liste résultante n'ajoute pas cette chaîne à la liste d'origine.
Merci, mais je ne demande pas comment accomplir réellement le casting. Je veux savoir pourquoi le compilateur permet la coulée même si elle est condamnée à échouer au moment de l'exécution.
@ZMBQ, car le compilateur ne fait pas ce genre d'analyse statique.
Si vous ne pouvez pas accéder à la liste code> sous-jacente code>, si vous pouvez accéder à la liste sous-jacente code>, p>
La raison pour laquelle la mise en forme implicite de La raison pour laquelle la fonte explicite p> stry> em> sera compilé, n'est pas que alors si un iList ilist L'interface IList t code>. Si, avec .NET 4.5, vous avez utilisé iReadonlist iList ilist liststring code>) peut être une classe (ou une structure) qui implémentait les deux interfaces! Supposons que j'ai faite cette classe: p> ilist Crazyliste code> au moment de l'exécution, La fonte explicite serait em> réussir. Lorsque vous écrivez une distribution explicite, vous dites au compilateur "Je sais que le type va être convertible à ce type que je jette dans". Puisque le compilateur ne peut pas prouver que vous avez tort, bien sûr, il vous croit. P> p>
@zmbq et vous pouvez faire une apparition explicite de toute interface i> à une autre interface i> autre interface pour la même raison, par exemple ICLONEABLEABLE MAILLEABLE = XXXX; Idisposable jetable = (isisposable) claquant; code>.
@ZMBQ, cela est également vrai pour les non génériques. L'idée de covariance est un hareng rouge ici. L'analyse statique nécessaire pour détecter l'erreur de développeur est coûteuse et généralement inutile.
Ceci est un problème de covariance par le livre. S'il vous plaît voir Stackoverflow.com/questions/5832094/covariant-and-ilist
Dupliqué possible de Covariant en C #
Et de commenter votre raisonnement. Qu'essayez-vous est logiquement faux. C'est pourquoi le compilateur n'aime pas. Essayer de le forcer en utilisant une distribution explicite ne va pas vous aider. L'utilisation d'une fonte explicite est comme dire "Je me fiche de quel type ceci est, il suffit de le compiler".
Je pose des questions sur l'incohérence dans le comportement - pourquoi la moulage explicite est-elle autorisée si elle échoue?
Parce que les moules ne sont vérifiées que lors de l'exécution. Ils ne sont jamais vérifiés lors de la compilation, car une distribution, par définition, utilise des informations que le compilateur ne sait pas (sinon une conversion implicite serait autorisée).
@Checoop, ce n'est tout simplement pas vrai. Essayez
(double) DateTime.now code>, le compilateur ne le permettra pas.@Euphoric, pourquoi le casting explicite existe-t-il? Cela ne devrait pas être là, comme cela échouera toujours. Dans quelles circonstances réussira-t-elle?
Il réussira lorsque le type interne de l'objet est assigné au type converti. Quelque chose comme "objet o = nouveau a (); a a = (a) o" va réussir. Dans votre cas, ilist n'est pas assignable à IList .
@Euphorique, quand est i> une IList assignable à un ?
Jamais. C'est pourquoi il ne compilera pas. La coulée explicite est pour les cas où vous êtes sûr que le type est assignable. Vous utilisez "is" opérateur pour le vérifier. En outre, vérifiez «comme» opérateur. Il retournera NULL au lieu d'échouer.
@ZMBQ: Oups. Ouais. C'est plus compliqué que "jamais". Mais ce qui compilera, c'est
(double) (objet) datetime.now code>Si le compilateur peut déterminer avec certitude, la distribution ne pourrait jamais réussir, elle n'est pas autorisée. Par exemple, un
struct code> ou unClasse scellée code> ne peut pas être dérivé. Le compilateur sait donc exactement quelles interfaces il met en œuvre et connaît toutes ses classes de base. Tellement essayer de jeter une classe ou une classe scellée à quelque chose de sans rapport n'est pas autorisé à compiler. D'autre part, une classe qui n'est pas scellée peut être explicitement moulée à aucune interface i> car une personne aurait pu hériter de la classe et que la classe dérivée implémente l'interface "non liée". Et ainsi de suite ...