5

I was playing around with using an lvalue as a result of conditional operator (cond ? expr1 : expr2).

Consider following example

class /*(1)*/ Value {
    public int MagicNumber { get; private set; } = 0;
    public void Increment() {
        /* magical code, that modifies MagicNumber */
    }
}

void Main()
{
    Value v1, v2;
    /*(2)*/ bool condition = /*...*/;
    (condition ? v1 : v2).Increment(); // (3)
}

Now, I would suspect, based on value of condition, that either v1 or v2 gets incremented. That actually is the case, as long as Value ((1)) is class. Once I change it to struct, it becomes Value type and line (3) does nothing (I would suspect because either v1 or v2 is copied, incremented and discarded). Up to this, it makes sense. The weird behavior begins once (2) (condition) is known at compile time (for example by defining it const bool). Then some optimalization comes to play and one of v1 or v2 is actually incremented in place.

My question is, what should be the correct behavior of conditional operator in following case

(condition ? v1 : v2).Increment();

once v1 and v2 is struct. Should it really depend on condition being compile-time constant?

Zereges
  • 5,139
  • 1
  • 25
  • 49
  • 1
    You are correct that when it's a struct it's creating a copy. That's why mutable structs are evil. http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil – juharr Mar 12 '17 at 00:55
  • 1
    The C# compiler does not perform a lot of optimizations, but it does tackle a const expression like this. The quirky behavior is why you usually see "don't mutate a struct!" advice posted at SO. Not that pretty, value types are a leaky abstraction in C#. I think you should click the [New Issue button](https://github.com/dotnet/roslyn/issues) and let the Microsoft engineers weigh on the matter. I doubt they'll fix it, but who knows. – Hans Passant Mar 12 '17 at 00:57

1 Answers1

1

As suggested, I've sent bug report to the Microsoft and it turned out, that standard does not explicitly says whether result of conditional operator is r-value (value) or l-value (variable). By transitivity of other things in the standard, it seems, that result should be an r-value.

It was decided that the bug should be fixed and the fix is already on it's way.

Zereges
  • 5,139
  • 1
  • 25
  • 49