ドキュメントから:
As演算子はキャストに似ていますが、例外が発生する代わりに変換の失敗時にnullが生成される点が異なります。より正式には、フォームの式:
expression as type
以下と同等です。
expression is type ? (type)expression : (type) null
ただし、式は1回だけ評価されます。
それで、なぜあなたはそれをどちらかの方法で行うことを選択しないのですか?なぜ2つの鋳造システムがあるのですか?
キャスティングの2つのシステムではありません。 2つのアクションは似ていますが、意味が大きく異なります。 「として」は、「このオブジェクトmightが実際にこの他のタイプであると思う;そうでない場合はnullを与える」を意味します。キャストとは、次のいずれかを意味します。
このオブジェクトが実際にはこの別のタイプであることは確かです。そのようにし、私が間違っている場合は、プログラムをクラッシュさせます。
このオブジェクトが他のタイプではないことは確かですが、現在のタイプの値を目的のタイプに変換する方法はよく知られています。 (たとえば、intをshortにキャストします。)そうして、変換が実際に機能しない場合は、プログラムをクラッシュさせます。
詳細については、この件に関する私の記事を参照してください。
予想どおりにキャストできない場合は失敗する場合もあれば、気にせずにキャストできない場合に特定のオブジェクトを破棄する場合もあります。
これは基本的に、tryブロックでラップされた通常のキャストのより高速なバージョンです。しかしAs
の方がはるかに読みやすく、入力も簡単です。
効率とパフォーマンス
キャストの実行の一部は、統合された型チェックです。したがって、明示的な型チェックを実際のキャストの前に付けることは冗長です(型チェックは2回発生します)。 as
キーワードを使用すると、実行される型チェックは1つだけになります。 「しかし、2番目の型チェックの代わりにnullチェックを行う必要がある」と考えるかもしれませんが、nullチェックは型チェックと比較して非常に効率的でパフォーマンスが優れています。
if (x is SomeType )
{
SomeType y = (SomeType )x;
// Do something
}
2xチェックを行いますが、
SomeType y = x as SomeType;
if (y != null)
{
// Do something
}
1xになります-型チェックに比べてnullチェックは非常に安価です。
メッセージベースの継承ツリーを処理するために必要となる場合がある、try/castオーバーヘッドなしの高速チェックを可能にします。
私はそれをかなり頻繁に使用します(メッセージを受け取り、特定のサブタイプに反応します)。 try/castは大幅に遅くなります(通過するすべてのメッセージの多くのtry/catchフレーム)-ここでは、1秒あたり200.000メッセージの処理について説明します。
私は通常、コードのセマンティクスに基づいてどちらか一方を選択します。
たとえば、object
があり、それがstring
でなければならないことがわかっている場合、(string)
を使用します。これは、コードを書く人がオブジェクトがstring
であり、そうでない場合は、スローされるランタイムキャスト例外よりも大きな問題が既に発生しています。
オブジェクトが特定のタイプかどうかわからないが、そのタイプに応じたロジックが必要な場合は、as
を使用します。 is
演算子に続けてキャストを使用することもできますが、as
演算子の方が効率的です。
両方を使用する実際のシナリオを紹介します。
public class Foo
{
private int m_Member;
public override bool Equals(object obj)
{
// We use 'as' because we are not certain of the type.
var that = obj as Foo;
if (that != null)
{
return this.m_Member == that.m_Member;
}
return false;
}
}
そして...
public class Program
{
public static void Main()
{
var form = new Form();
form.Load += Form_Load;
Application.Run(form);
}
private static void Form_Load(object sender, EventArgs args)
{
// We use an explicit cast here because we are certain of the type
// and we want an exception to be thrown if someone attempts to use
// this method in context where sender is not a Form.
var form = (Form)sender;
}
}
多分例が役立つでしょう:
// Regular casting
Class1 x = new Class1();
Class2 y = (Class2)x; // Throws exception if x doesn't implement or derive from Class2
// Casting with as
Class2 y = x as Class2; // Sets y to null if it can't be casted. Does not work with int to short, for example.
if (y != null)
{
// We can use y
}
// Casting but checking before.
// Only works when boxing/unboxing or casting to base classes/interfaces
if (x is Class2)
{
y = (Class2)x; // Won't fail since we already checked it
// Use y
}
// Casting with try/catch
// Works with int to short, for example. Same as "as"
try
{
y = (Class2)x;
// Use y
}
catch (InvalidCastException ex)
{
// Failed cast
}