usar unario ternario solo operator operadores operador logicos ejemplos como asignacion c# lambda conditional-operator

c# - unario - ¿Cómo puedo asignar un Func<> condicionalmente entre lambdas usando el operador ternario condicional?



operator c# (3)

Generalmente, cuando se usa el operador condicional, aquí está la sintaxis:

int x = 6; int y = x == 6 ? 5 : 9;

Nada elegante, bastante directo.

Ahora, intentemos usar esto cuando asignamos un Lambda a un tipo de Func. Dejame explicar:

Func<Order, bool> predicate = id == null ? p => p.EmployeeID == null : p => p.EmployeeID == id;

Esa es la misma sintaxis, y debería funcionar? ¿Derecha? Por alguna razón, eso no. El compilador da este agradable mensaje críptico:

Error 1 El tipo de expresión condicional no se puede determinar porque no hay una conversión implícita entre ''expresión lambda'' y ''expresión lambda''

Luego seguí adelante y cambié la sintaxis y de esta manera funcionó:

Func<Order, bool> predicate = id == null ? predicate = p => p.EmployeeID == null : predicate = p => p.EmployeeID == id;

Tengo curiosidad de por qué no funciona de la primera manera?

(Nota al margen: terminé sin necesitar este código, ya que descubrí que al comparar un valor int con nulo, solo usa object.Equals)


El compilador de C # no puede inferir el tipo de la expresión lambda creada porque procesa el ternario primero y luego la asignación. también podrías hacer:

Func<Order, bool> predicate = id == null ? new Func<Order,bool>(p => p.EmployeeID == null) : new Func<Order,bool>(p => p.EmployeeID == id);

pero eso apesta, también podrías probar

Func<Order, bool> predicate = id == null ? (Order p) => p.EmployeeID == null : (Order p) => p.EmployeeID == id;


Permítanme tener mi propio ejemplo ya que también tuve el mismo problema (con la esperanza de que el ejemplo sea útil para otros):

Mi método Find es un método genérico que obtiene Expression<Func<T, bool>> como predicado y da List<T> como salida.
Quería encontrar países, pero los necesito todos si la lista de idiomas estaba vacía, y la lista filtrada, si la lista de idiomas estaba completa. Primero utilicé el Código de la siguiente manera:

var countries= Find(languages.Any() ? (country => languages.Contains(country.Language)) : (country => true));

Pero exactamente obtengo el error: there is no implicit conversion between lambda expression and lambda expression.

El problema es que tenemos solo dos expresiones lambda aquí, y nada más, por ejemplo, ¿qué es country => true exactamente? Tenemos que determinar el tipo de al menos una de las expresiones lambda . Si solo se determina una de las expresiones, entonces se omitirá el error. Pero para hacer el código más legible, extraje ambas expresiones lambda y usé la variable en su lugar, como se muestra a continuación:

Expression<Func<Country, bool>> getAllPredicate = country => true; Expression<Func<Country, bool>> getCountriesByLanguagePredicate = country => languages.Contains(country.Language); var countries= Find(languages.Any() ? getCountriesByLanguagePredicate : getAllPredicate);

Insisto en que, si acabo de determinar el tipo de expresión, el error será reparado.


Puede convertir una expresión lambda en un tipo particular de delegado objetivo, pero para determinar el tipo de expresión condicional, el compilador necesita saber el tipo de cada uno de los operandos segundo y tercero. Si bien ambos son solo "expresión lambda", no hay conversión de uno a otro, por lo que el compilador no puede hacer nada útil.

Sin embargo, no recomendaría usar una tarea: un reparto es más obvio:

Func<Order, bool> predicate = id == null ? (Func<Order, bool>) (p => p.EmployeeID == null) : p => p.EmployeeID == id;

Tenga en cuenta que solo necesita proporcionarlo para un operando, por lo que el compilador puede realizar la conversión desde la otra expresión lambda.