2012-07-03 24 views
18

Estoy tratando de usar el operador condicional (ternario) para asignar la expresión lambda adecuada a una variable, dependiendo de una condición, pero obtengo el error del compilador: Tipo de la expresión condicional no se puede determinar porque no hay una conversión implícita entre 'expresión lambda' y 'expresión lambda'. Puedo usar el if-else regular para resolver este problema, pero el operador condicional tiene más sentido para mí (en este contexto), haría que el código sea más conciso, al menos, me gustaría saber las razones por las que no funciona. t trabajo.Asignar una expresión lambda utilizando el operador condicional (ternario)

// this code compiles, but is ugly! :) 
Action<int> hh; 
if (1 == 2) hh = (int n) => Console.WriteLine("nope {0}", n); 
else hh = (int n) => Console.WriteLine("nun {0}", n); 

// this does not compile 
Action<int> ff = (1 == 2) 
    ? (int n) => Console.WriteLine("nope {0}", n) 
    : (int n) => Console.WriteLine("nun {0}", n); 
+0

Gracias por su prontitud rich.okelly, Nikhil Agrawal, Romain Verdier y Alex! Todas sus respuestas fueron correctas (compilar y dar el resultado correcto), pero mi elección va a rich.okelly debido a su explicación. –

Respuesta

18

El compilador de C# trata de crear la lambdas de forma independiente y no se puede determinar sin ambigüedades el tipo.Fundición puede informar al compilador qué tipo de uso:

Action<int> ff = (1 == 2) 
    ? (Action<int>)((int n) => Console.WriteLine("nope {0}", n)) 
    : (Action<int>)((int n) => Console.WriteLine("nun {0}", n)); 
15

Esto funcionará.

Action<int> ff = (1 == 2) 
? (Action<int>)((int n) => Console.WriteLine("nope {0}", n)) 
: (Action<int>)((int n) => Console.WriteLine("nun {0}", n)); 

Hay dos problemas aquí

  1. Expresión
  2. ternario operador

1. Problema con la expresión

el compilador diciéndole exactamente lo que está mal - 'Type of conditional expression cannot be determined because there is no implicit conversion between 'lambda expression' and 'lambda expression'.

Significa que lo que ha escrito es expresión lambda y la variable resultante también es expresión lambda.

La expresión lambda no tiene ningún tipo particular, es simplemente convertible al árbol de expresiones.

Una expresión del acceso de miembros (que es lo que estás tratando de hacer) está disponible sólo en las formas

primary-expression . identifier type-argument-list(opt) 
predefined-type . identifier type-argument-list(opt) 
qualified-alias-member . identifier type-argument-list(opt) 

... y una expresión lambda no es una expresión primaria.

2. Problema con ternario operador

Si hacemos

bool? br = (1 == 2) ? true: null; 

Esto da lugar a error que dice exactamente como la suya. 'Type of conditional expression cannot be determined because there is no implicit conversion between 'bool' and '<null>'

Pero el error se ha ido si hacemos esto

bool? br = (1 == 2) ? (bool?)true: (bool?)null; 

Fundición de un lado también trabajará

bool? br = (1 == 2) ? (bool?)true: null; 

O

bool? br = (1 == 2) ? true: (bool?)null; 

para su caso

Action<int> ff = (1 == 2) 
? (Action<int>)((int n) => Console.WriteLine("nope {0}", n)) 
: ((int n) => Console.WriteLine("nun {0}", n)); 

O

Action<int> ff = (1 == 2) 
? ((int n) => Console.WriteLine("nope {0}", n)) 
: (Action<int>)((int n) => Console.WriteLine("nun {0}", n)); 
+0

+1 rápido y perfecto – Habib

+0

excelente respuesta, directamente al grano con ejemplos claros ... gracias – Dal

+0

@Dal: Gracias. :) –

3

Básicamente la misma respuesta que los demás, en una forma diferente

Action<int> ff = (1 == 2) 
? new Action<int>(n => Console.WriteLine("nope {0}", n)) 
: new Action<int>(n => Console.WriteLine("nun {0}", n)); 
4

De hecho, la inferencia de tipos, se puede:

  • Use var para la variable local
  • Solo eche la primera expresión del operador ternario
  • Omita el tipo del parámetro lambda ya que se puede inferir

El resultado es mucho más conciso. (Le dejo decidir si es más legible.)

var ff = condition 
      ? (Action<int>)(n => Console.WriteLine("nope {0}", n)) 
      : n => Console.WriteLine("nun {0}", n); 
Cuestiones relacionadas