C# is operator, exact behavior of unboxing

Viewed 98

The C# language specification doc about the is operator reads:

The result of the operation E is T, where E is an expression and T is a type, is a boolean value indicating whether E can successfully be converted to type T by a reference conversion, a boxing conversion, or an unboxing conversion. [...]

[...] let D represent the dynamic type of E as follows:

  • If the type of E is a reference type, D is the run-time type of the instance reference by E.
  • If the type of E is a nullable type, D is the underlying type of that nullable type.
  • If the type of E is a non-nullable value type, D is the type of E.
    The result of the operation depends on D and T as follows: [... goes on with the target type]

Then the documentation goes on with a similar distinction about the target type. Since I'm only interested in the expression's type, I that part and also the null cases that are not relevant for this question.

When I have something like that:

object s = "hey";
if (s is string) ...

It's the first case that applies.

When I have something like that:

int? nullableInt = 10;
if (nullableInt is int) ...

It's the second case that applies: E is a nullable type and int is its underlying type. Pretty useless.

But when i have something like that, that is a value boxed into an object, it seems like there is a missing rule.

object o = (int)10;
if (o is int) ...

Here the static type of the expression is object, that is a referece type, while its run-time type is a value type.
This is a very (maybe the most) common scenario for type-testing.
Since the static type of the expression is a reference type, it should be the first case that applies.
But when the 'content' of the reference type is a value type, it should apply rules like 2 and 3 for the boxed value, behavior that I confirmed via test. But this is not what the documentation says; it seems to me that the boxing case is missing. Is this analysis correct or it's me missing something?

1 Answers

In your example, the expression E corresponds to your variable o. Its (static) type is object, and its runtime type is int.

Then according to this rule

If the type of E is a reference type, D is the run-time type of the instance reference by E.

the dynamic type D of E is int, since "type" in the antecedent of the rule refers to the static type, which in our case is indeed a reference type.

The definition of the is operator further specifies

If T is a non-nullable value type, the result is true if D and T are the same type.

In this case, T corresponds to int (since your are testing o is int). Hence o is int is true, since D and T are both int.

Related