7

次のことを考慮してください。

Object box = 5;
int @int = (int)box;  // int = 5
int? nullableInt = box as int?; // nullableInt = 5;
StringComparison @enum = (StringComparison)box; // enum = OrdinalIgnoreCase
StringComparison? nullableEnum = box as StringComparison?; // nullableEnum = null.

2つのこと::

  1. 箱を開けるのはなぜStringComparisonですか?これは、基になるタイプがであるためだと思いますがInt32、それでも奇妙だと思います。
  2. なぜnullableEnumnullの値を持つのですか?

私が理解しているように、ボックス化された値型からの唯一の有効なアンボックス化は、その型またはnull許容型です。intにボックスを解除できる場合Enum、null許容値に同じことが当てはまらないのはなぜですか?同様に、5の代わりにボックス化StringComparison.OrdinalIgnoreCaseした場合、それはnullableIntnullになりますが、nullableEnumそうではありません。

4

3 に答える 3

3

厳密に言えば、のバグ C#仕様によると、ランタイムの実装の詳細

nullable-typeにアンボックス化すると、ソースオペランドがnullの場合はnullable-typeのnull値が生成され、それ以外の場合は、オブジェクトインスタンスをnullable-typeの基になるタイプにアンボックス化した結果がラップされます。

つまり、StringComparisonへのボックス化解除が機能する場合は、Nullable<StringComparison>へのボックス化解除も機能するはずです。両方が機能するのか、両方が失敗するのかは少しわかりません。スペックによると

特定のnull許容値以外の値型へのボックス化解除変換を実行時に成功させるには、ソースオペランドの値が、そのnull許容値以外の値型のボックス化された値への参照である必要があります。

StringComparisonの基になる型はintであるため、ボックス化されたintがStringComparison型のボックス化された値と見なされるかどうかを決定する必要があります。仕様では、ボックスに「互換性のないオブジェクト」が含まれている場合、InvalidCastExceptionがスローされるとされています。ヒープからStringComparison変数に4バイトを安全にコピーできるため、intはStringComparisonと確かに「互換性があります」。

于 2010-10-26T18:43:41.073 に答える
1

列挙型または整数をオブジェクトにキャストしても、型情報は保持されます。だからbox is StringComparison戻りfalseます。ただし、任意の列挙型またはintを任意の列挙型にキャストできるため、明示的なキャストが(StringComparison)box機能します。これは列挙型の特殊なケースです。Nullable<T>一方、は通常のクラスであり、タイプをキャストまたはチェックするときにTは特定の方法で処理されません。これが、このコードが例外をスローする理由です。

        StringComparison? nullableEnum = (StringComparison?)nullableInt;
于 2010-10-26T18:02:40.563 に答える
-1

1)はい、列挙型の基になるタイプはintであり、それがこのように機能する理由です。さらに。次のことができます。

enum MyEnum
{
    One = 1,
    Two = 2,
}

int i = 3;
MyEnum myEnum = (MyEnum)i; // This works without exceptions.

2)それStringComparison?は実際Nullable<StringComparison>には異なるタイプだからです。また、as演算子は、オブジェクトが演算子として指定されたものと同じタイプであるかどうかのみをチェックします。

于 2010-10-26T17:49:06.687 に答える