Domanda

public class Foo : IFooBarable {...}
public class Bar : IFooBarable {...}

Allora, perché sarà mai questo non compilare ...

int a = 1;
IFooBarable ting = a == 1 ? new Foo() : new Bar();

Ma questo ...

IFooBarable ting = a == 1 ? new Foo() : new Foo();
IFooBarable ting = a == 1 ? new Bar() : new Bar();
È stato utile?

Soluzione

Il compilatore prima prova per valutare l'espressione a destra:

? new Foo() : new Bar();

Non c'è conversione implicita tra i due, quindi, il messaggio di errore. Si può fare questo:

IFooBarable ting = a == 1 ? (IFooBarable)(new Foo()) : (IFooBarable)(new Bar());

Altri suggerimenti

Questo è trattato nella sezione 7.13 della specifica linguaggio C #. In sostanza ciò che sta uccidendo questo scenario è che ci deve essere una conversione implicita tra i tipi dei 2 valori per gli operandi ternari. Questa conversione è considerato nel abscence del tipo della variabile.

Quindi, o Foo deve essere convertibile in Bar o viceversa. Nessuno dei due è così si verifica un errore di compilazione.

Quest'ultimo 2 lavoro però perché considerano solo 1 tipo (sia Foo o Bar). Perché sono dello stesso tipo di determinare il tipo dell'espressione è semplice e funziona bene.

Giusto per aggiungere un po 'per le risposte corrette pubblicati qui: ci sono due linee guida di progettazione che portano a questa specifica

.

La prima è che abbiamo ragione da "dall'interno verso l'esterno". Quando si dice

double x = 2 + y;

siamo lavorare il tipo di x, allora il tipo di 2, allora il tipo di y, allora il tipo di (2 + y), e infine, possiamo stabilire se x e (2 + y) sono compatibili tipi. Ma noi non utilizzare il tipo di x nel decidere quale tipo di 2, Y o 2 + y è.

Il motivo di questo è una buona regola è perché spesso il tipo di "ricevente" è esattamente ciò che stiamo cercando di capire:

void M(Foo f) {}
void M(Bar b) {}
...
M(x ? y : z);

Che cosa dobbiamo fare qui? Dobbiamo lavorare il tipo dell'espressione condizionale al fine di fare la risoluzione di sovraccarico, al fine di determinare se questo sta per Foo o al bar. Pertanto, non possiamo usare il fatto che questo è, diciamo, andando a Foo nella nostra analisi del tipo dell'espressione condizionale! Questo è un problema di pollo e uova.

L'eccezione a questa regola è espressioni lambda, che Do prendere il loro tipo dal loro contesto. Fare questo lavoro funzione correttamente era follemente complicato; vedere il mio serie di blog sulle espressioni lambda vs metodi anonimi, se siete interessati.

Il secondo elemento è che non abbiamo mai "magia" un tipo per voi. Quando somministrato un sacco di cose da cui dobbiamo dedurre un tipo, abbiamo sempre dedurre un tipo che era in realtà proprio di fronte a noi.

Nel tuo esempio, l'analisi va in questo modo:

  • capire il tipo di conseguenza
  • capire il tipo di alternativa
  • trovare il tipo migliore che è compatibile sia con la conseguenza e l'alternativa
  • assicurarsi che non v'è una conversione dal tipo dell'espressione condizionale per il tipo di cosa che utilizza l'espressione condizionale.

In linea con il primo punto, noi non ragioniamo di fuori-di-dentro ; non usiamo il fatto che conosciamo il tipo della variabile che andremo a al fine di elaborare il tipo di espressione. Ma la cosa interessante è che ora quando si ha

b ? new Cat() : new Dog()

diciamo "il tipo dell'espressione condizionale è il tipo migliore nel set {gatto, cane}". Noi non diciamo "il tipo dell'espressione condizionale è il tipo migliore compatibile sia con Gatto e cane". Sarebbe Mammifero, ma noi non lo facciamo. Invece, diciamo "il risultato deve essere qualcosa in realtà abbiamo visto", e di queste due scelte, né è il chiaro vincitore. Se lei ha detto

b ? (Animal) (new Cat()) : new Dog()

allora abbiamo una scelta tra animali e cani, e degli animali è il chiaro vincitore.

Ora, notare che in realtà non implementano correttamente il C # spec quando si fa questo tipo di analisi! Per dettagli dell'errore, vedere il mio articolo su di esso.

Poiché il tipo dell'espressione condizionale è sempre dedotto dalle sue due parti, non dalla variabile a cui il risultato deve essere applicato. Questa deduzione funziona solo quando i tipi sono uguali o uno è compatibile riferimento all'altro. In questo caso, nessuno dei due tipi è compatibile riferimento all'altra.

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