Pregunta

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

Entonces, ¿entonces esto no compilación ...

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

Pero esto ...

IFooBarable ting = a == 1 ? new Foo() : new Foo();
IFooBarable ting = a == 1 ? new Bar() : new Bar();
¿Fue útil?

Solución

Los primeros intentos del compilador para evaluar la expresión de la derecha:

? new Foo() : new Bar();

No hay conversión implícita entre los dos por lo tanto, el mensaje de error. Usted puede hacer esto:

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

Otros consejos

Esto se explica en la sección 7.13 de la especificación del lenguaje C #. En esencia lo que está matando a este escenario es que debe haber una conversión implícita entre los tipos de los 2 valores para los operandos ternarios. Esta conversión se considera en el abscence del tipo de la variable.

Así que, o Foo debe ser convertible en Bar o viceversa. Tampoco es para que se produzca un error de compilación.

Estos últimos 2 trabajo, sin embargo, ya que sólo tienen en cuenta el tipo 1 (ya sea Foo o Bar). Debido a que son del mismo tipo para determinar el tipo de la expresión es simple y funciona bien.

Sólo para añadir un poco a las respuestas correctas publicadas aquí: hay dos directrices de diseño que conducen a esta especificación

.

La primera es que la razón de "dentro a fuera". Cuando usted dice

double x = 2 + y;

que primero trabajo a cabo el tipo de x, entonces el tipo de 2, entonces el tipo de y, a continuación, el tipo de (2 + y), y finalmente, se trabaja a cabo si x y (2 + y) tenemos compatible tipos. Pero nosotros no usamos el tipo de x para decidir cuál es el tipo de 2, y 2 o + y es.

La razón de que esto es una regla buena es porque a menudo el tipo del "receptor" es exactamente lo que estamos tratando de averiguar:

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

Lo que vamos a hacer aquí? Tenemos que trabajar a cabo el tipo de la expresión condicional con el fin de hacer sobrecarga de resolución, con el fin de determinar si esto va a Foo o bar. Por lo tanto, no puede uso el hecho de que se trata, por ejemplo, va a Foo en nuestro análisis del tipo de la expresión condicional! Eso es un problema de la gallina y el huevo.

La excepción a esta regla es expresiones lambda, que DO toman su tipo de su contexto. Hacer que el trabajo adecuadamente característica se complicó locamente; ver a mi series Blog en las expresiones lambda vs métodos anónimos si está interesado.

El segundo elemento es que nunca "mágica" un tipo para ti. Cuando se le da un montón de cosas de las que hay que deducir un tipo, siempre deducir un tipo que era en realidad justo en frente de nosotros.

En el ejemplo, el análisis es el siguiente:

  • trabajo fuera del tipo de la consecuencia
  • trabajo fuera del tipo de la alternativa
  • encontrar el mejor tipo que es compatible tanto con la consecuencia y la alternativa
  • asegurarse de que hay una conversión del tipo de la expresión condicional para el tipo de cosa que está utilizando la expresión condicional.

De acuerdo con el primer punto, no razonamos de fuera a dentro ; no usamos el hecho de que conocemos el tipo de la variable que vamos a trabajar con el fin de determinar el tipo de la expresión. Pero lo interesante ahora es que cuando se tiene

b ? new Cat() : new Dog()

Decimos "el tipo de la expresión condicional es el mejor tipo en el conjunto {gato, perro}". No decimos "el tipo de la expresión condicional es el mejor tipo compatible tanto con gato y el perro". Eso sería Mamífero, pero no hacemos eso. En lugar de ello, decimos "el resultado tiene que ser algo que de hecho vimos", y de esas dos opciones, tampoco lo es el claro ganador. Si usted dijo

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

A continuación, tenemos una elección entre el animal y el perro, y el animal es el claro ganador.

Ahora, nota que en realidad no aplicamos correctamente la especificación C # cuando se hace este tipo de análisis! Para más detalles acerca del error, ver a mi artículo en él.

Debido a que el tipo de la expresión condicional siempre se infiere de sus dos partes, no desde la variable a la que el resultado es que debe aplicarse. Esta deducción sólo funciona cuando los tipos son iguales o uno es compatible con referencia a la otra. En este caso, ninguno de los dos tipos es compatible con referencia a la otra.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top