Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why ternary operator doesn't replace if-else

Tags:

c#

I've met a little problem and a knowledge gap

I found using If-Else style is too boilerplate sometimes and wanted to replace it with elvis-operator, for example:

Dictionary<string, List<List<int>> VarsWithInfo;

want to replace:

if (VarsWithInfo.ContainsKey(ruleVar))
    {
        VarsWithInfo[ruleVar] = new List<List<int>> { NestingBlocks };
    }
else
    {
        VarsWithInfo[ruleVar].Add(NestingBlocks);
    }

with that:

VarsWithInfo.ContainsKey(ruleVar) ?
    VarsWithInfo[ruleVar] = new List<List<int>> { NestingBlocks } :
    VarsWithInfo[ruleVar].Add(NestingBlocks);

I know that line with ternar operator is too long in this case, but I want to know the primary reason. Thank you.

like image 267
strelok 372 Avatar asked Dec 18 '22 15:12

strelok 372


1 Answers

The conditional operator ?:, commonly known as the ternary conditional operator, evaluates a Boolean expression, and returns the result of evaluating one of two expressions, depending on whether the Boolean expression evaluates to true or false

From MSDN

The ternary operator always returns a value. In the expression x = a ? b : c, if a is true then it will assign the value of b to x, otherwise it will assign the value of c to x.

Therefore both b and c need to be expressions which result in a value, and both of those values need to be of the same type.

Neither VarsWithInfo[ruleVar] = new List<List<int>> { NestingBlocks } nor VarsWithInfo[ruleVar].Add(NestingBlocks) are expressions, and they do not return a value. Therefore they cannot be used in a ternary.


I'm assuming your code was supposed to be:

if (!VarsWithInfo.ContainsKey(ruleVar))
{
    VarsWithInfo[ruleVar] = new List<List<int>> { NestingBlocks };
}
else
{
    VarsWithInfo[ruleVar].Add(NestingBlocks);
}

A common way of writing this is:

if (!VarsWithInfo.TryGetValue(ruleVar, out var list))
{
    list = new List<List<int>>();
    VarsWithInfo[ruleVar] = list;
}
list.Add(NestingBlocks);

This avoids the duplicate dictionary lookup (i.e. calling VarsWithInfo.ContainsKey(ruleVar) and then reading from VarsWithInfo[ruleVar]).

like image 123
canton7 Avatar answered Dec 24 '22 02:12

canton7