Assign a lambda expression using the conditional (

2019-01-25 03:52发布

I am trying to use the conditional (ternary) operator to assign the proper lambda expression to a variable, depending on a condition, but I get the compiler error: Type of conditional expression cannot be determined because there is no implicit conversion between 'lambda expression' and 'lambda expression'. I can use the regular if-else to solve this problem, but the conditional operator makes more sense to me (in this context), would make the code more concise add, at least, I would like to know the reasons why it doesn't work.

// 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);

标签: c# lambda
4条回答
倾城 Initia
2楼-- · 2019-01-25 04:06

In fact, with type inference, you can:

  • Use var for the local variable
  • Only cast the first expression of the ternary operator
  • Omit the type of the lambda parameter since it can be inferred

The result is much more concise. (I let you decide if it's more readable.)

    var ff = condition 
             ? (Action<int>)(n => Console.WriteLine("nope {0}", n)) 
             : n => Console.WriteLine("nun {0}", n);
查看更多
Summer. ? 凉城
3楼-- · 2019-01-25 04:13

The C# compiler tries to create the lambdas independently and cannot unambiguously determine the type. Casting can inform the compiler which type to use:

Action<int> ff = (1 == 2)
  ? (Action<int>)((int n) => Console.WriteLine("nope {0}", n))
  : (Action<int>)((int n) => Console.WriteLine("nun {0}", n));
查看更多
神经病院院长
4楼-- · 2019-01-25 04:13

Basically the same answer as others, in a different form

Action<int> ff = (1 == 2) 
? new Action<int>(n => Console.WriteLine("nope {0}", n)) 
: new Action<int>(n => Console.WriteLine("nun {0}", n));
查看更多
Root(大扎)
5楼-- · 2019-01-25 04:15

This will work.

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

There are two problems here

  1. Expression
  2. Ternary Operator

1. Problem with Expression

The compiler is telling you exactly what's wrong - 'Type of conditional expression cannot be determined because there is no implicit conversion between 'lambda expression' and 'lambda expression'.

It means what you have written is lambda expression and the resultant variable is also lambda expression.

The lambda expression doesn't have any particular type - it's just convertible to the expression tree.

A member-access expression (which is what you're trying to do) is only available in the forms

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

... and a lambda expression isn't a primary expression.

2. Problem with Ternary Operator

If we do

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

This results in error saying exactly like yours. 'Type of conditional expression cannot be determined because there is no implicit conversion between 'bool' and '<null>'

But error is gone if we do this

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

Casting of one side will also work

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

OR

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

For your case

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

OR

Action<int> ff = (1 == 2)
? ((int n) => Console.WriteLine("nope {0}", n))
: (Action<int>)((int n) => Console.WriteLine("nun {0}", n)); 
查看更多
登录 后发表回答