Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this code invalid in C#?

The following code will not compile:

string foo = "bar"; Object o = foo == null ? DBNull.Value : foo; 

I get: Error 1 Type of conditional expression cannot be determined because there is no implicit conversion between 'System.DBNull' and 'string'

To fix this, I must do something like this:

string foo = "bar"; Object o = foo == null ? DBNull.Value : (Object)foo; 

This cast seems pointless as this is certainly legal:

string foo = "bar"; Object o = foo == null ? "gork" : foo; 

It seems to me that when the ternary branches are of different types, the compiler will not autobox the values to the type object...but when they are of the same type then the autoboxing is automatic.

In my mind the first statement should be legal...

Can anyone describe why the compiler does not allow this and why the designers of C# chose to do this? I believe this is legal in Java...Though I have not verified this.

Thanks.

EDIT: I am asking for an understanding of why Java and C# handle this differently, what is going on underneath the scenes in C# that make this invalid. I know how to use ternary, and am not looking for a "better way" to code the examples. I understand the rules of ternary in C#, but I want to know WHY...

EDIT (Jon Skeet): Removed "autoboxing" tag as no boxing is involved in this question.

like image 892
mmattax Avatar asked Oct 14 '08 18:10

mmattax


People also ask

What is a invalid C expression?

The “invalid use of void expression” error occurs in C/C++ when we try to assign a call to a void function to a variable. It also occurs when a void function is cast to another data type.

How do you make this program ask for input again if invalid input is entered in C programming?

2 Answers. Show activity on this post. while(scanf("%f",&num1)==0) //Taking Input Here Once { printf("Invalid input. Please enter a number."); scanf("%f",&num1); //Again Taking input. }


1 Answers

The compiler requires that either the types of second and third operands are the same, or that one is implicitly convertible to the other. In your case, the types are DBNull and string, neither of which is implicitly convertible to the other. Casting either of them to object solves that.

EDIT: Looks like it is indeed legal in Java. Quite how it works out what to do when it comes to method overloading, I'm not sure... I've just looked at the JLS, and it's extremely unclear about what the type of the conditional is when there are two incompatible reference types involved. The C# way of working may be more irritating occasionally, but it's clearer IMO.

The relevant section of the C# 3.0 spec is 7.13, the conditional operator:

The second and third operands of the ?: operator control the type of the conditional expression. Let X and Y be the types of the second and third operands. Then,

  • If X and Y are the same type, then this is the type of the conditional
  • Otherwise, if an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
  • Otherwise, if an implicit conversion (§6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
  • Otherwise, no expression type can be determined, and a compile-time error occurs.
like image 138
Jon Skeet Avatar answered Oct 11 '22 18:10

Jon Skeet