web-dev-qa-db-ja.com

null許容型へのC#キャスト?

BeyondCastAsの通常の退屈な違い

  • if iknowthatAppleFruitなので、(Fruit)Apple-それが適切でない場合、例外をスローします
  • as valueをnullと照合して、成功したかどうかを確認できます[例外をスローしません...]

しかし、私はこれについて@EricLippert article を読んでおり、Nullable Value Typesに関する素晴らしいサンプルがありました:

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

これはコンパイルされません...

タイプ「short?」を変換できません「int?」参照変換、ボックス化変換、ボックス化解除変換、ラッピング変換、またはnull型変換を介して

ファイン。

なぜこれ:

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

Doesコンパイル? (Against ALL Expectations!I[〜#〜] know [〜#〜]that sint?ではありません-そしてBANGになるはずですが、そうではありません...)

ここでのキャストチェックは、前の例(Bangに行った)よりもはるかに致命的です。

私はこのよく話題になっている主題について尋ねるのは気分が悪い。

前もって感謝します。

29
Royi Namir

最初の例では、as演算子はオブジェクトsint?として使用しようとします。 int?short?の継承チェーンのどこにもないため、この操作は失敗します。

2番目の例では、実際にint? iの値で新しいshort? sを作成しています。左側の元のsオブジェクトを保持する必要がないため、これはより寛大な操作です。

ここで重要な点は、asがオブジェクトのIDを保持しないことを許可されていないことです。明示的なキャストは可能です。

以下は、C#標準が(int?)フォームがどのように機能するかについて述べているものです。

6.1.4暗黙的なNULL可能変換

Nullを許可しない値型を操作する定義済みの暗黙的な変換は、これらの型のnullを許可する形式でも使用できます。 Nullを許容しない値型SからNullを許容しない値型Tに変換する定義済みの暗黙のIDおよび数値変換のそれぞれについて、次の暗黙のNull許容変換が存在します。

・Sからの暗黙的な変換? Tに?.

・SからT?への暗黙的な変換。

SからTへの基礎となる変換に基づく暗黙的なNULL可能変換の評価は、次のように進行します。

ヌル可能変換がSからのものである場合Tへ:

oソース値がnull(HasValueプロパティがfalse)の場合、結果はT?型のnull値になります。

oそれ以外の場合、変換はSからのラップ解除として評価されますか? SからTへの基本的な変換、それに続くTからTへのラッピング(§4.1.10)が続きます。

ヌル可能変換がSからT?への変換である場合、変換は、SからTへの基礎となる変換と、それに続くTからT?へのラッピングとして評価されます。

25
sblom

例:

int? i = (int?)s;

コンパイラは、キャストが推測できないこと、つまりsint?に変換できることを知っていることをコンパイラに伝えるために、コンパイラを実行します。

キャストが成功しなかった場合にのみ、実行時に例外が発生します。

4
Oded

asが失敗した場合、「有効な」nullの結果が表示されるため、それが原因だと思うので、false positiveです。 2番目のケースでは、キャストが許可されているため、失敗した場合は例外が発生します。

0
Tigran

理由はそのintですか? System.Nullable<int>の省略形です(System.Nullable<T>がタイプです)。 short型はintへの明示的なキャストを定義しますが、Tは他の値型である可能性があるため、System.Nullable<T>にはそのような明示的なキャストはありません。

0
Andy