简体   繁体   中英

Using ternary operator: “only assignment, call, increment…”

I have action dictionary defined as:

var actions = new Dictionary<string, Action<string, string>>();

I put there actions like:

actions.Add("default", (value, key) => result.Compare(value, properties[key], Comparers.SomeComparer, key));
...

I'm using this code to run it:

if (actions.ContainsKey(pair.Key))
{
    actions[pair.Key](pair.Value, pair.Key);
}
else
{
    actions[""](pair.Value, pair.Key);
}

It works just fine, but I wanted to use '?' notation to make it shorter:

actions.ContainsKey(pair.Key) ? actions[pair.Key](pair.Value, pair.Key) : actions[""](pair.Value, pair.Key);

This code shows me error:

Error 1 Only assignment, call, increment, decrement, and new object expressions can be used as a statement

actions[pair.Key](pair.Value, pair.Key) isn't it a call? Am I missing something? Is it possible to use '?' notation with action dictionaries? I was trying to find something about that but it's hard to find anything about '?' operator and this error because '?' is ignored by google.

Try this instead:

actions[actions.ContainsKey(pair.Key) ? pair.key : ""](pair.Value, pair.Key);

This will fix your issue.

The ?: Conditional operator is defined as:

The conditional operator (?:) returns one of two values depending on the value of a Boolean expression

Your actions don't return a value, so what is the return value of ?: meant to be?

If you realy have to do it that way, you could try

actions[actions.ContainsKey(pair.Key) ? pair.Key : ""](pair.Value, pair.Key);

Just to clarify, from : Operator (C# Reference)

The condition must evaluate to true or false. If condition is true, first_expression is evaluated and becomes the result. If condition is false, second_expression is evaluated and becomes the result. Only one of the two expressions is evaluated.

this is equivelant

int input = Convert.ToInt32(Console.ReadLine());
string classify;

// if-else construction.
if (input < 0)
    classify = "negative";
else
    classify = "positive";

// ?: conditional operator.
classify = (input < 0) ? "negative" : "positive";

There's nothing wrong with your call, per se. The expression actions[pair.Key](pair.Value, pair.Key) is indeed a call. That's not the expression the compiler's complaining about, though. The compiler is referring to the entire conditional-operator expression, which is neither an assignment, call, increment, decrement, nor new object expression, and is therefore not allowed to be a statement by itself.

Alternatives include the following:

  • Assigning the result of the expression to another variable, making the conditional merely a sub-expression of the larger assignment statement
  • Factoring the conditional into the index expression, so the overall statement is a single call rather than two separate calls.
  • Using two independent statements to decide which key to use and then call the function:

     var key = actions.ContainsKey(pair.Key) ? pair.Key : ""; actions[key](pair.Value, pair.Key); 

    It still avoids duplicating code, but keeps things more easily readable by not trying to pack everything into one complex statement.

every "? :" statement need to assign to something, meaning that

actions.ContainsKey(pair.Key) ? actions[pair.Key](pair.Value, pair.Key) : actions[""](pair.Value, pair.Key);

isn't legal because it's not assigning anything.

you can do:

object x = actions.ContainsKey(pair.Key) ? actions[pair.Key](pair.Value, pair.Key) : actions[""](pair.Value, pair.Key);

and that would be legal if actions[pair.Key](pair.Value, pair.Key) and actions[""](pair.Value, pair.Key); return a value

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM