鋳造:(ニュータイプ) vs.NewType としてのオブジェクト [重複]
質問
重複の可能性:
CLR でのキャストと「as」キーワードの使用
実際、この 2 つのキャストの違いは何でしょうか?
SomeClass sc = (SomeClass)SomeObject;
SomeClass sc2 = SomeObject as SomeClass;
通常、両方とも指定された型に明示的にキャストする必要がありますか?
解決
前者は、ソース型をターゲット型にキャストできない場合に例外をスローします。後者の場合、sc2 は null 参照になりますが、例外は発生しません。
[編集]
私の最初の答えは確かに最も顕著な違いですが、エリック・リッパートのように 指摘している, 、それだけではありません。その他の違いは次のとおりです。
- 「as」演算子を使用して、値として「null」を受け入れない型にキャストすることはできません。
- 「as」を使用することはできません 変換する 数値を別の表現に変換する (たとえば、float を int に変換するなど)。
そして最後に、「as」と対を使用します。キャスト オペレーターも、「これが成功するかどうかはわかりません」と言っていることになります。
他のヒント
また、 as キーワードは参照型または null 許容型でのみ使用できることに注意してください。
つまり:
double d = 5.34;
int i = d as int;
コンパイルされません
double d = 5.34;
int i = (int)d;
コンパイルされます。
もちろん、「as」を使用した型キャストは、例外をスローするコストを回避できるため、キャストが失敗した場合にはるかに高速です。
ただし、キャストが成功した場合は速くなりません。のグラフ http://www.codeproject.com/KB/cs/csharpcasts.aspx 何を測定しているのか説明していないため、誤解を招きます。
結論は次のとおりです。
キャストが成功すると予想される場合 (つまり、失敗は例外的です)、キャストを使用します。
成功するかどうかわからない場合は、「as」演算子を使用して、結果が null かどうかをテストします。
2 つのアプローチの違いは、最初の ((SomeClass)obj) が原因で問題が発生する可能性があることです。 タイプコンバータ 呼ばれることに。
ここでは、どちらが自分の状況に適しているかを判断するときに使用する、それぞれのプロセスを覚えておく良い方法を紹介します。
DateTime i = (DateTime)value;
// is like doing
DateTime i = value is DateTime ? value as DateTime : throw new Exception(...);
そして次はそれが何をするのか簡単に推測できるはずです
DateTime i = value as DateTime;
最初のケースでは、値をキャストできない場合は例外がスローされます。2 番目のケースでは、値をキャストできない場合は、i が null に設定されます。
したがって、最初のケースではハード停止が行われ、2 番目のキャストでキャストが失敗するとソフト停止が行われ、後で NullReferenceException が発生する可能性があります。
良い 「as」演算子は、問題をより低い位置に埋めるのに「役立ちます」 互換性のないインスタンスが提供されると null が返されるため、おそらくそれを別のメソッドに渡すメソッドに渡すことになり、最終的に NullReferenceException が発生してデバッグが困難になります。
悪用しないでください。99% の場合、直接キャスト演算子の方が優れています。
さらに拡張するには リトミスさんのコメント, は使用できません。 として 構造体 (値型) には null 値がないため、キーワードを使用します。
これはすべて参照型に適用され、値型は as
null にすることはできないため、キーワードを使用します。
//if I know that SomeObject is an instance of SomeClass
SomeClass sc = (SomeClass) someObject;
//if SomeObject *might* be SomeClass
SomeClass sc2 = someObject as SomeClass;
キャスト構文は高速ですが、成功した場合に限り、失敗した場合ははるかに遅くなります。
ベストプラクティスは使用することです as
種類がわからないときは、
//we need to know what someObject is
SomeClass sc;
SomeOtherClass soc;
//use as to find the right type
if( ( sc = someObject as SomeClass ) != null )
{
//do something with sc
}
else if ( ( soc = someObject as SomeOtherClass ) != null )
{
//do something with soc
}
ただし、絶対にそう確信している場合は、 someObject
の例です SomeClass
次にキャストを使用します。
.Net 2 以降では、ジェネリックスは、参照クラスの型なしインスタンスを持つ必要がほとんどないことを意味するため、後者はあまり使用されません。
括弧内のキャストは、キャストの試行が失敗した場合に例外をスローします。キャスト試行が失敗した場合、「as」キャストは null を返します。
さまざまな例外がスローされます。
() :NullReferenceException
として :無効なキャスト例外
これはデバッグに役立つ可能性があります。
「as」キーワードはオブジェクトのキャストを試行し、キャストが失敗した場合は、通知なしで null が返されます。() キャスト演算子は、キャストが失敗した場合にすぐに例外をスローします。
C# の "as" キーワードは、キャストが例外的ではない場合に失敗することが予想される場合にのみ使用してください。キャストが成功することを期待していて、失敗するオブジェクトを受け取る準備ができていない場合は、() キャスト演算子を使用して、適切で役立つ例外がスローされるようにする必要があります。」
コード例と詳細な説明については、以下を参照してください。 http://blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html
これは、Parse と TryParse の違いのようなものです。TryParse は失敗するかもしれないと予想される場合に使用しますが、失敗しないという強い確信がある場合には Parse を使用します。
VB.NET の経験がある方にとって、(type) は DirectCast と同じであり、「as type」は TryCast と同じです。