Domanda

Ecco cosa voglio fare:

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

Ciò non viene compilato, tuttavia, fornendo l'errore "Il tipo di espressione condizionale non può essere determinato perché non esiste una conversione implicita tra" System.IO.TextWriter "e" stringa "" ;. Il codice sopra riportato è una semplificazione di quanto segue:

XmlWriter writer;

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

Queste due chiamate a Crea sono perfettamente valide e questo viene compilato. C'è un modo per renderlo più compatto, come stavo cercando di fare con il mio test in linea?

Non ha senso per me che ciò che voglio non funziona. Pensando mentalmente a ciò, sembra che il compilatore valuti string.IsNullOrEmpty (outfile) per determinare quale caso prendere:

  • Se la condizione fosse vera, andrebbe con Console.Out , e quindi vedrebbe che deve scegliere polimorficamente la versione di XmlWriter.Create che accetta un TextWriter .
  • Se la condizione fosse falsa, andrebbe con outfile , e quindi vedrebbe che deve scegliere polimorficamente la versione di XmlWriter.Create che accetta una stringa.

La programmazione in ML ha deformato il mio cervello?

È stato utile?

Soluzione

Il motivo per cui non puoi farlo è perché il compilatore deve scegliere quale sovraccarico di Crea usare in fase di compilazione - il tuo approccio richiederebbe che venga eseguito in fase di esecuzione. Il più breve che puoi fare è probabilmente:

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

Altri suggerimenti

Tutti sembrano suggerire quanto segue:

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

Tuttavia, anche questo è fattibile:

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

Quest'ultimo è più vicino al tuo tentativo originale e, IMO, più compatto.

Il compilatore C # sceglie un metodo per eseguire staticamente durante la compilazione. L'IL che viene generato durante la compilazione è un riferimento a un metodo specifico. La parte del polimorfismo entra in fase di esecuzione quando sceglie quale implementazione di quella specifica funzione eseguire.

L'istruzione Your?: viene valutata in fase di esecuzione e pertanto il compilatore non è in grado di capire quale metodo eseguire.

Passa a questo e funzionerà.

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

Il problema è che non è possibile determinare in fase di compilazione cosa

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

dovrebbe tornare. Sarà una stringa o sarà un TextWriter? Ciò può essere determinato solo in fase di esecuzione, quindi l'errore di compilazione perché? l'operatore deve essere risolto al momento della compilazione.

Il meglio che puoi ottenere sarebbe probabilmente:

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

Qui stanno accadendo un paio di cose.

Innanzitutto, la "eccezione" si verifica a causa di The Ternary Operator (tm), non a causa di dove lo stai usando. Il problema è perché hai un'unica espressione che sta cercando di restituire due diversi tipi che non possono essere risolti in un singolo tipo di base comune (diverso dall'oggetto).

Inoltre, i sovraccarichi del costruttore probabilmente assumono due tipi completamente diversi che non sono in alcun modo correlati. Il compilatore C # è molto, molto intelligente, ma non è abbastanza così intelligente.

No, devi effettuare due chiamate separate, poiché sono due costruttori separati.

Quale sovraccarico chiamare è determinato al momento della compilazione, quindi non è possibile selezionare un tipo di dati in fase di esecuzione per chiamare sovraccarichi diversi.

Inoltre, l'operatore condizionale può restituire un solo tipo di dati, non è possibile che restituisca tipi di dati diversi a seconda della scelta.

C # è tipizzato staticamente tutto il polimorfismo che la magia sta avvenendo in fase di compilazione. E il tipo della tua espressione condizionale non è noto al momento della compilazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top