switch and nullable type in C# 2.0

  • Thread starter Thread starter Octavio Hernandez
  • Start date Start date
Hi

VS 2005 beta 2 successfully compiles the following:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1 {
class Program {
enum A { a, b, c }
static void Main(string[] args) {
A? aaaa = null;
switch (aaaa) {
case null:
Console.WriteLine("null");
break;
default:
Console.WriteLine("def");
break;
}
}
}
}

Any comments on nullables in switch?

Thank you
Yuri
 
hi,

which types are allowed in switch? string and integral types?
or any type, if there is only one way of implicit convertion to any of the
types mentioned above.

Nullable<> is neither string nor integral type, and I cannot find anything
where it is said that C# 2.0 enhances a list of types allowed in switch.

yuriy
 
Yuriy said:
which types are allowed in switch? string and integral types? or any
type, if there is only one way of implicit convertion to any of the types
mentioned above.

Nullable<> is neither string nor integral type, and I cannot find anything
where it is said that C# 2.0 enhances a list of types allowed in switch.

Here's what the specs say (C# 1.2):

The governing type of a switch statement is established by the switch
expression. If the type of the switch expression is sbyte, byte, short,
ushort, int, uint, long, ulong, char, string, or an enum-type, then that
is the governing type of the switch statement. Otherwise, exactly one
user-defined implicit conversion (§?6.4) must exist from the type of the
switch expression to one of the following possible governing types: sbyte,
byte, short, ushort, int, uint, long, ulong, char, string. If no such
implicit conversion exists, or if more than one such implicit conversion
exists, a compile-time error occurs.

The constant expression of each case label must denote a value of a type
that is implicitly convertible (§?6.1) to the governing type of the switch
statement. A compile-time error occurs if two or more case labels in the
same switch statement specify the same constant value.



Oliver Sturm
 
What is Nullable<A> in this list? Do you know any implicit convertions from
A? to any of the types listed in spec?

yuriy
 
Yuri,

Quoting the C# Specification, 3rd Edition (p. 228):

"The governing type of a switch statement is established by the switch
expression. If the type of the switch
expression is sbyte, byte, short, ushort, int, uint, long, ulong, char,
string, or an enum-type,

then that is the governing type of the switch statement. Otherwise, exactly
one user-defined implicit

conversion operator (§13.4) shall exist from the type of the switch
expression or a base type of this type to

one of the following possible governing types: sbyte, byte, short, ushort,
int, uint, long, ulong,

char, string. If no such implicit conversion operator exists, or if more
than one such implicit conversion

operator exists, a compile-time error occurs."

This covers the case of a nullable type as switch expression, right?

The standard is at www.ecma-international.org.

Privet - Octavio
 
Yuriy said:
What is Nullable<A> in this list? Do you know any implicit convertions
from A? to any of the types listed in spec?

A Nullable<T> can be used in a switch statement if T itself has an
implicit conversion to one of the listed types, or is a listed type. In
your case, that's the Enum. If you try your sample with a Nullable<T>
where T is an arbitrary class, you'll see that the compiler complains
about it, even if you're still only checking for the null case.

I wonder why you're wondering about this so much... to my mind, this
construct behaves just like one would think it should, doesn't it? IOW, if
a type T can be used in a switch, then T? can be used as well, and can
additionally be checked for the null case. Makes a lot of sense to me.


Oliver Sturm
 
Nullable<Snum> is not enum itself. It is just value type, which has no implicit
conversion to niether the enum or listed type. so, according to your explanation
in cannot be used in switch, but it works.
 
Yuriy said:
Nullable<Snum> is not enum itself. It is just value type, which has no
implicit conversion to niether the enum or listed type. so, according to
your explanation in cannot be used in switch, but it works.

I wasn't saying that Nullable<Enum> is an Enum. I'm sure the conversion
that's taking place is actually covered by paragraph 24.2 of the C# 2.0
specs - read it if you like, I guess the relevant point for your sample is
the last one in 24.2.2:

If the nullable conversion is from S? to T, the conversion is evaluated as an unwrapping from S? to S followed by the underlying conversion from S to T.

If you decompile a program similar to your sample, you'll see that the
compiler creates calls to the GetValueOrDefault method of the Nullable<T>,
before the comparison itself takes place. This allows for constructs like

int? foo = 42;
if (foo == 42)
...

Or of course for the use of the Nullable<T> in a switch statement, such as
we were discussing.


Oliver Sturm
 
How does it cover nullables? SomeEnum type is not base type for Nullable said:
Yuri,

Quoting the C# Specification, 3rd Edition (p. 228):

"The governing type of a switch statement is established by the switch
expression. If the type of the switch
expression is sbyte, byte, short, ushort, int, uint, long, ulong,
char,
string, or an enum-type,
then that is the governing type of the switch statement. Otherwise,
exactly one user-defined implicit

conversion operator (§13.4) shall exist from the type of the switch
expression or a base type of this type to

one of the following possible governing types: sbyte, byte, short,
ushort, int, uint, long, ulong,

char, string. If no such implicit conversion operator exists, or if
more than one such implicit conversion

operator exists, a compile-time error occurs."

This covers the case of a nullable type as switch expression, right?

The standard is at www.ecma-international.org.

Privet - Octavio
 
In this case 42 is converted to int?, but it does not explain how switch
works. Specifications says that it must be either listed type or implicit
conversion to the listed type must exist.
 
Hi Octavio,
see comment inline

Octavio Hernandez said:
Yuri,

Quoting the C# Specification, 3rd Edition (p. 228):

"The governing type of a switch statement is established by the switch
expression. If the type of the switch
expression is sbyte, byte, short, ushort, int, uint, long, ulong, char,
string, or an enum-type,

a nullable type is non if this types, right?
then that is the governing type of the switch statement. Otherwise,
exactly one user-defined implicit

conversion operator (§13.4) shall exist from the type of the switch
expression or a base type of this type to

one of the following possible governing types: sbyte, byte, short, ushort,
int, uint, long, ulong,

char, string. If no such implicit conversion operator exists, or if more
than one such implicit conversion

There is no user-defined conversion operator from a nullable type (if its
not defined by the user.), right?
 
If the nullable conversion is from S? to T, the conversion is evaluated as
an unwrapping from S? to S followed by the underlying conversion from S to T.

The nullable conversion from S? to T is an Explicit conversion.
This allows for constructs like

int? foo = 42;
if (foo == 42)

This is using the lifted == operator, which is covered in 14.2.7 of the ecma
spec.
 
but with VS2005beta2 you can compile it and it works..

I cannot find anyplace in the spec that would explain why it compiles. I
think this is an interesting question and I will take another look when I
have more time.

Note that the C# compiler also lets you switch on bool (which is a compiler
bug).
 
Sorry, Yura!

Now I understand what you mean. Very interesting!

Regards - Octavio
 
MarkT said:
The nullable conversion from S? to T is an Explicit conversion.

I would think so, too, but that's nevertheless exactly what the generated
code shows.


Oliver Sturm
 
Any comments on nullables in switch?

I just spent an hour looking at every place either nullable or switch
appears in the spec, and I could not find anything that explains the
behavior. However, the spec is pretty tough reading so I could easily have
missed something. I tentatively vote "bug" on this one. You could submit it
as a bug in the Microsoft Product Feedback Center to get some official word
on it.
 
MarkT said:
I just spent an hour looking at every place either nullable or switch
appears in the spec, and I could not find anything that explains the
behavior. However, the spec is pretty tough reading so I could easily have
missed something. I tentatively vote "bug" on this one. You could submit
it
as a bug in the Microsoft Product Feedback Center to get some official
word
on it.

Note that only the latest v2.0 beta version (2.0.50727) includes the latest
Design Change Request made for VS2005 and the CLR, one of these DCR relate
to nullable types, maybe one could try this using this build.
Note that it's allways safe to file an issue to Product Feedback though.

Willy.
 
Back
Top