C# casting to nullable type?

2019-03-22 15:46发布

问题:

Beyond the regular boring difference between Cast and As

  • if i know that apple is a Fruit so I can use (Fruit)apple - and it throws an exception if it aint
  • as value can be checked against null to see if succeeded [won't throw Exception...]

However Ive been reading @EricLippert article about this and there was a nice sample about Nullable Value Types :

short? s = (short?)123;
int? i = s as int?;

this won't compile...

Cannot convert type 'short?' to 'int?' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion

Fine.

so why this :

    short? s = (short?)123;
    int? i = (int?)s;

Does Compile ? ( Against ALL Expectations ! I KNOW that s is not int? - and it should go BANG but it aint ...)

the Cast checking here should be much more deadly than the former example (which went Bang)

I feel bad asking about this much-talked subject.

Thanks in Advance.

回答1:

In your first example, the as operator attempts to use the object s as an int?. Since int? isn't anywhere in the inheritance chain of short?, this operation fails.

In your second example, you're actually creating a new int? i with the value from short? s. This is a more generous operation, because it doesn't have to preserve the original s object on the left hand side.

The important point here is that as isn't allowed to do anything that doesn't preserve your object's identity. An explicit cast can.

Here's what the C# standard says about how the (int?) form works:

6.1.4 Implicit nullable conversions

Predefined implicit conversions that operate on non-nullable value types can also be used with nullable forms of those types. For each of the predefined implicit identity and numeric conversions that convert from a non-nullable value type S to a non-nullable value type T, the following implicit nullable conversions exist:

· An implicit conversion from S? to T?.

· An implicit conversion from S to T?.

Evaluation of an implicit nullable conversion based on an underlying conversion from S to T proceeds as follows:

· If the nullable conversion is from S? to T?:

o If the source value is null (HasValue property is false), the result is the null value of type T?.

o Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping (§4.1.10) from T to T?.

· If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?.



回答2:

The example:

int? i = (int?)s;

Does compiler because a cast is you telling the compiler that you know something that it can't infer, that is, that s can be converted to a int?.

You will only get the exception at runtime if the cast is not successful.



回答3:

I think it's cause in case of as failure you will be given a "valid" null result, so false positive. In second case, cast is allowed cause in case of failure it will raise an exception.



回答4:

The reason is that int? is just shorthand for System.Nullable<int> (System.Nullable<T> is the type). The short type defines an explicit cast to an int, however System.Nullable<T> doesn't have any such explicit cast, because T could be any other value type.