The ternary operator is often unable to determine left/right side result types.
Specifically, you won't be able to write:
xxx ? () => { } : () => { }
because ()=>{}
has no specific type in C#. This expression can be automatically converted to, for example, System.Action
, but the compiler won't guess it has to do it, if there's no hint anywhere. And with this exact form as above, there's no hint.
In such cases, try to be more specific and leave as little to be inferred as possible, and often that'll fix it.
var myAction = doIt ? new Action(() => { myBool = false; }) : new Action(() => { });
or this may also work:
var myAction = doIt ? new Action(() => { myBool = false; }) : () => { }; // should work
or even
Action myAction = doIt ? () => { myBool = false; } : () => { }; // really doubtful, probably not
since it has a specific type in at least one place, so other sides may be inferred. I'm not sure though, I didn't check it with a real compiler. First version with two new-Action will work for sure.
In your case, there also was a problem with that extra ;
before :
.
After de-oneline'ing it and formatting in a bit odd way, it's:
var myAction =
doIt
? new Action(() => { myBool = false; })
: new Action(() => { })
;
and here you see that each of those lambdas is a clean ()=>{ }
with no following ;
, and that ?:
has a format of condition ? whentrue : whenfalse
and that the ;
only is at the end of whole var foo = value;
expression.
--
EDIT: since you asked about casting like
var myAction = doIt ? (Action)(() => { myBool = false; }) : () => { };
please note that it looks more or less the same, just as unreadable as any other lambda+?:, and saves you exactly 2 characters as compared to:
var myAction = doIt ? new Action(() => { myBool = false; }) : () => { };
With casting, you still have to provide a full type name of the Action, and use parentheses around the lambda, so the difference is only between new
and ()
, so 2 characters. I usually don't use casting unless absolutely necessary, so I'd go with new
here.
Also, since ?:
+ lambdas quickly gets illegible, and since the ()=>{}
fallback is actually a perfectly reuseable no-op, there's not much reason for creating tons of such delegate objects, so my code would actually probalby look like this:
// elsewhere in some utility class
public static readonly Action NoOp = () => { };
...
var myAction = !doIt ? Utils.NoOp : () => { myBool = false; };
// or, if code block is larger
var myAction = !doIt ? Utils.NoOp : () => {
logic logic
myBool = false;
logic logic
};
or, if for some reason, it can't be reused, then:
Action nah = () => {
logic logic
logic logic
logic logic
};
Action yea = () => {
logic logic
myBool = false;
logic logic
};
var myAction = doIt ? yea : nah;
I know the last one directly breaks the original idea you had about placing it in one line, but since I already discuss different formatting and code layout, then, really. More than one lambda in a single line is very bad for readability, and unless those lambdas are trivial, your coworkers or future readeres of that code will probably be grateful for this expanded layout :)