1

Consider the following method:

public object Foo(bool flag)
{
    if (flag) 
        return (new object(), new object());
    return (null, new object()); //Compiler error over here!!
}

This does not compile showing the error I mentioned in the title of this question. I can fix that with just a cast like the following:

public object Foo(bool flag)
{
    if (flag) 
        return (new object(), new object());
    return ((object)null, new object());
}

So far so good. The weird part and the reason for which I am asking this is that if I change the syntax and I use ternary operator instead of if-else statement like this:

public object Boo(bool flag) => flag
                                ? (new object(), new object())
                                : (null, new object());

Then no cast is needed!!! Why? IMHO both ways of writing the method are semantically equal. I know that the IL generated may not be the same (haven't checked that).

maccettura
  • 10,514
  • 3
  • 28
  • 35
taquion
  • 2,667
  • 2
  • 18
  • 29
  • @Chris the compiler error is in the title: CS8135: Tuple with 2 elements cannot be converted to type object – taquion Sep 05 '18 at 18:10
  • Ah, my apologies. I was looking for it in the body! I see you've edited it to make it clearer now though, thanks. I would imagine it is to do with type inference - the first one it doesn't know what type the null is, the second one fixes that and the third one knows because both outputs of the ternary must be the same type. This theory doesn't match the error message though so I am not sure if it is correct or if there is more to it... – Chris Sep 05 '18 at 18:14
  • Possible duplicate of [Required casting using C# ternary conditional operator](https://stackoverflow.com/questions/33108900/required-casting-using-c-sharp-ternary-conditional-operator) – Rufus L Sep 05 '18 at 18:19
  • @RufusL: Related but not a duplicate. The conditional is shown here to demonstrate an approach that also works, but it's not the focus of the question. – Jeff Mercado Sep 05 '18 at 18:24

1 Answers1

7

The problem is that the null expression has no definite type, it depends on the context in which it is used. In the case of the conditional operator, the compiler has to find a common type between (object, object) and (null, object). In that case it can deduce that null may be object.

When the compiler sees (null, object) and needs to convert to object, the value null can be a multitude of types thus the error. It's the same reason why it cannot infer a type for lambdas unless you give it a hint.

Action x = () => { }; // ok
var y = () => { }; // error

As an aside, rather than using (object)null as the value, I would strongly suggest using default(object) instead that way you're not tying yourself to a specific value, but rather a value appropriate for the type you give.

Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272