2010-08-23 5 views
1

Je rencontre des erreurs de compilation inattendues avec ce code:erreur bizarre du compilateur lors de la coulée dans l'opérateur ternaire/conditionnelle

bool b = true; //or false 
StringBuilder builder = ...; // a string builder filled with content 
IVersePart vp = b ? (DualLanguageVersePart)builder : (VersePart)builder; 

Les deux DualLanguageVersePart et VersePart implémenter l'interface IVersePart. Les deux DualLanguageVersePart et VersePart ont un opérateur de cast explicite StringBuilder.

Puisque les deux classes implémenter l'interface qui est le type de vp, je m'attendrais à ce que cela fonctionne parfaitement, ou au moins compile correctement. Au lieu de cela, le compilateur signale qu'aucune conversion implicite ne peut être effectuée entre les deux types.

Pourquoi cela ne fonctionne-t-il pas?

+0

duplication possible de [Types nullable et l'opérateur ternaire. Pourquoi cela ne fonctionnera-t-il pas?] (Http://stackoverflow.com/questions/858080/nullable-types-and-the-ternary-operator-why-wont-this-work) – BFree

+0

Vous décrivez une erreur de compilation, mais ne fournit pas le texte d'erreur exact ou le numéro de ligne sur lequel il apparaît. Cela pourrait être une information importante, tu crois? – abelenky

Répondre

1

J'ai eu ce problème auparavant, l'opérateur ternaire requiert que les deux types de résultat vrai ou faux soit du même type ou que vous les transtypiez au même type.

+0

Pas vrai. Il suffit que le type d'un opérande soit un sous-type de l'autre. –

2

Les deux parties doivent avoir le même type, alors essayez ceci:

IVersePart vp = b ? 
    (IVersePart)(DualLanguageVersePart)builder : 
    (IVersePart)(VersePart)builder; 

Le compilateur C# est fussier sur ce que le compilateur C++ :)

+0

Le compilateur C++ décent ne le permet pas non plus. Au moins, GCC ne le fera pas. –

+0

Pourquoi les jetteriez-vous deux fois? Il suffit de les lancer une fois vers IVersePart et c'est bon. –

+1

Non, vous ne pouvez pas, car l'opérateur de distribution explicite crée une nouvelle instance de DualLanguageVersePart ou VersePart. – Excel20

0

L'opérateur ternaire doit être en mesure de revenir un type, comme c'est juste une seule déclaration. Ainsi, lorsque les deux parties de l'opérateur renvoient des types différents, le compilateur tentera de le faire en convertissant tranquillement l'un vers l'autre. Vous n'avez pas de conversion de DualLanguageVersePart en VersePart, ou vice versa.

Une solution simple consiste à ajouter que dans un second casting à IVersePart:

IVersePart vp = b ? (IVersePart)(DualLanguageVersePart)builder : (IVersePart)(VersePart)builder; 
0

Le ternaire fonctionne nécessite le vrai et le faux pour retourner le même type. Voici une façon de contourner cela, un peu bâclée ...

IVersePart vp = b 
    ? (IVersePart)((DualLanguageVersePart)builder) 
    : (IVersePart)((VersePart)builder); 
2

Ceci est une mauvaise conception. Les opérateurs de casting ne devraient pas être utilisés comme ça.

Il serait préférable d'avoir un cteur pour gérer ce (comme vous êtes, en fait d'essayer de construire un nouvel objet)

IVersePart vp = new DualLanguageVersePart(builder); 

Alternativement, vous pouvez utiliser une usine:

IVersePart vp = VersePart.DualOrSingluar(builder, b); 
-1

Le type de résultat de tout opérateur (autre que operator implicit) est déterminé par les opérandes et non par le contexte.

Contrairement à la plupart des idées fournies ici, les deux arguments ne doivent pas forcément être du même type. Si un type est dérivé de l'autre alors le résultat de l'opérateur ternaire sera le type de base. Mais dans votre exemple, il existe plusieurs types de base communs: au moins Object et IVersePart, et le langage C# n'incite pas le compilateur à déterminer lequel est le meilleur.

+0

Mais il y aura toujours 'Objet' et une interface commune dans ces scénarios. En quoi est-ce différent de toujours exiger le même type dans les deux opérandes? – Blindy

+0

Si un type d'opérande 'T' est un sous-type du type' S' de l'autre opérande, alors 'S' est un sur-ensemble de tous les types partagés (au moment de la compilation) et donc la meilleure conversion. Dans ce cas, cela signifie que la conversion de l'un des opérandes à 'IVersePart' est suffisante pour résoudre l'ambiguïté. Essayez-le. –

Questions connexes