26

次の構造体を定義しました。

public struct Call
{
    public SourceFile caller;
    public SourceFile callee;

    public Call(SourceFile caller, SourceFile callee)
    {
        this.caller = caller;
        this.callee = callee;
    }
}

後で、別のオブジェクトの Tag プロパティに割り当てます。

line.Tag = new Call(sf1, sf2);

しかし、そのようにTagプロパティを取得しようとすると、

Call call = line.Tag as Call;

Visual Studio では、次のコンパイル時エラーが発生します。

演算子 as は、参照型または null 許容型内で使用する必要があります

その意味は何ですか?どうすれば解決できますか?

4

6 に答える 6

36

既存の回答のいくつかは、完全に正しくありません。最初のオペランドが実際に適切な型でない場合、の結果はその型の null 値になるため、null 非許容型をで使用することはできません。asas

ただし、値の型で使用できasます... null 許容の場合:

int a = 10;
object o = a;

int? x = o as int?; // x is a Nullable<int> with value 10
long? y = o as long?; // y is a Nullable<long> with the null value

したがって、次を使用できます。

Call? call = line.Tag as Call?;

次に、次のように使用できます。

if (call != null)
{
    // Do stuff with call.Value
}

ただし、2 つの注意事項があります。

  • is私の経験では、これはキャストを使用するよりも遅いです
  • Call現在のタイプ を真剣に再考する必要があります。
    • public フィールドを公開していますが、これは一般的にカプセル化が不十分です。
    • これは可変値型であり、ほぼ間違いなく間違いです

代わりにクラスにすることを強くお勧めします-その時点で、とにかくこの問題はなくなります。

別の考え: タグが常にである必要がある場合はCall、キャストすることをお勧めします。

Call call = (Call) line.Tag;

そうすれば、データが期待と一致しない場合 (つまり、Tagが ではないバグがあるCall場合)、他の作業を行った後でなく、早い段階でそれを見つけることができます。このキャストCallは、構造体かクラスかによって動作が異なることに注意してください。null の場合Tagは、null 値を参照型 (または null 許容値型) の変数にキャストできますが、null 非許容値にはキャストできません。タイプ。

于 2010-12-09T17:46:02.077 に答える
34

構造体は値型なので、as演算子では使用できません。キャストが失敗した場合、演算子は nullのas値を割り当てることができなければなりません。これは、参照型または null 許容値型でのみ可能です。

これを解決するにはいくつかの方法がありますが、最善の策はCall型を構造体からクラスに変更することです。これにより、基本的に型が値型から参照型に変更されas、キャストが失敗した場合にオペレーターが null の値を割り当てることができます。

値型と参照型の詳細については、これがまともな記事です。また、MSDN を参照してください。

于 2010-12-09T17:42:58.433 に答える
12

C#仕様から

§7.10.11 as 演算子は、値を特定の 参照型またはnull 許容型に明示的に変換するために使用されます。キャスト式 (§7.7.6) とは異なり、as 演算子は例外をスローしません。代わりに、指定された変換が不可能な場合、結果の値はnullになります。

参照および null 許容型は null にすることができます。スタクトは値型であるため、null にすることはできません。

于 2010-12-09T17:46:26.707 に答える
1
Call? call = line.Tag as Call?;
于 2010-12-09T17:45:59.807 に答える
0

これは C# の制限です。型が参照型の場合、キャストが失敗した場合は単純に「null」を返しますが、値型であるため、キャストが失敗したときに何を返すかわかりません。

as の使用を、'is' と 'as' の 2 つに置き換える必要があります。

if (line.Tag is Call) {
  call = (Call)line.Tag;
} else {
  // Do whatever you would do if as returned null.
}
于 2010-12-09T17:43:50.953 に答える
-1

意味は何ですか - 述べたように、構造体は値型です。

どうすれば解決できますか-に変更します

Call call = line.Tag;
于 2010-12-09T17:46:08.333 に答える