Question

Voici ce que je veux faire:

XmlWriter writer = XmlWriter.Create(
    (string.IsNullOrEmpty(outfile) ? Console.Out : outfile)
);

Ceci ne compile pas, cependant, donner l'erreur "Le type de l'expression conditionnelle ne peut pas être déterminé car il n'y a pas de conversion implicite entre 'System.IO.TextWriter' et 'chaîne'". Le code ci-dessus est une simplification de ce qui suit:

XmlWriter writer;

if (string.IsNullOrEmpty(outfile))
{
    writer = XmlWriter.Create(Console.Out); // Constructor takes TextWriter
}
else
{
    writer = XmlWriter.Create(outfile); // Constructor takes string
}

Ces deux appels à Créer sont parfaitement valides et sont compilés. Existe-t-il un moyen de rendre cela plus compact, comme ce que j’essayais de faire avec mon test en ligne?

Cela n'a pas de sens pour moi que ce que je veux ne fonctionne pas. En réfléchissant mentalement à cela, il semble que le compilateur évalue string.IsNullOrEmpty (outfile) pour déterminer le cas à prendre:

  • Si la condition était vraie, cela irait avec Console.Out , puis verrait qu'il faut choisir de manière polymorphe la version de XmlWriter.Create prenant un TextWriter. .
  • Si la condition était fausse, cela irait avec outfile , puis verrait qu'il faut choisir de manière polymorphe la version de XmlWriter.Create qui prend une chaîne.

La programmation en ML a-t-elle faussé mon cerveau?

Était-ce utile?

La solution

La raison pour laquelle vous ne pouvez pas le faire est que le compilateur doit choisir la surcharge de Create à utiliser au moment de la compilation - votre approche nécessiterait que cela soit fait au moment de l'exécution. Le plus court que vous puissiez faire est probablement:

XmlWriter writer = String.IsNullOrEmpty(outfile)
    ? XmlWriter.Create(Console.Out)
    : XmlWriter.Create(outfile);

Autres conseils

Tout le monde semble suggérer ceci:

XmlWriter writer = String.IsNullOrEmpty(outfile)
    ? XmlWriter.Create(Console.Out)
    : XmlWriter.Create(outfile);

Cependant, cela est également faisable:

XmlWriter writer = XmlWriter.Create(string.IsNullOrEmpty(outfile)
    ? Console.Out : new StreamWriter(outfile));

Ce dernier est plus proche de votre tentative initiale et, IMO, plus compact.

Le compilateur C # choisit une méthode à exécuter de manière statique lors de la compilation. L'IL généré lors de la compilation est une référence à une méthode spécifique. La partie polymorphisme intervient au moment de l’exécution quand elle choisit l’implémentation de cette fonction spécifique à exécuter.

Votre instruction?: est évaluée au moment de l'exécution et le compilateur ne peut donc pas déterminer la méthode à exécuter.

Changez pour ceci et ça fonctionnera.

XmlWriter writer = string.IsNullOrEmpty(outfile) ? 
    XmlWriter.Create(Console.Out) :
    XmlWriter.Create(outfile);

Le problème est que vous ne pouvez pas déterminer au moment de la compilation ce que

(string.IsNullOrEmpty(outfile) ? Console.Out : outfile)

devrait revenir. Est-ce que ce sera une chaîne ou est-ce que ce sera un TextWriter? Cela ne peut être déterminé qu'au moment de l'exécution, d'où l'erreur de compilation car le? l'opérateur doit être résolu au moment de la compilation.

Le mieux que vous puissiez en tirer serait probablement:

XmlWriter writer = string.IsNullOrEmpty(outfile)
    ? XmlWriter.Create(Console.Out)
    : XmlWriter.Create(outfile);

Il se passe quelque chose ici.

Tout d’abord, l’exception "exception" se produit à cause de The Ternary Operator (tm), pas à cause de l'endroit où vous l'utilisez. Le problème est que vous avez une seule expression qui essaie de renvoyer deux types différents qui ne peuvent pas être résolus en un seul type de base commun (autre qu'un objet).

De plus, vos surcharges de constructeur prennent probablement deux types complètement différents qui ne sont aucunement liés. Le compilateur C # est très, très intelligent, mais ce n'est pas aussi intelligent .

Non, vous devez effectuer deux appels distincts, car ce sont deux constructeurs distincts.

La surcharge à appeler est déterminée lors de la compilation. Vous ne pouvez donc pas sélectionner un type de données au moment de l'exécution pour appeler différentes surcharges.

En outre, l'opérateur conditionnel ne peut renvoyer qu'un seul type de données. Vous ne pouvez pas le faire renvoyer des types de données différents selon le choix choisi.

C # est statiquement typé, toute la magie du polymorphisme se passe au moment de la compilation. Et le type de votre expression conditionnelle n’est pas connu au moment de la compilation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top