Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
これはエラーです。C#のtypeof演算子は、オブジェクトではなく型名のみを使用できます。
if (obj1.GetType() == typeof(int))
// Some code here
これは機能しますが、おそらく期待どおりではありません。ここで示したように、値の型の場合は許容されますが、参照型の場合は、型が完全に同じ型であり、継承階層の他のものではない場合にのみtrueを返します。例えば:
class Animal{}
class Dog : Animal{}
static void Foo(){
object o = new Dog();
if(o.GetType() == typeof(Animal))
Console.WriteLine("o is an animal");
Console.WriteLine("o is something else");
}
これは、印刷し"o is something else"
の種類があるため、o
あるDog
、ありませんAnimal
。ただし、クラスのIsAssignableFrom
メソッドを使用すれば、これを機能させることができますType
。
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
ただし、この手法には依然として大きな問題があります。変数がnullの場合、への呼び出しGetType()
はNullReferenceExceptionをスローします。したがって、正しく機能させるには、次のようにします。
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
これにより、is
キーワードと同等の動作になります。したがって、これが目的の動作である場合は、is
より読みやすく効率的なキーワードを使用する必要があります。
if(o is Animal)
Console.WriteLine("o is an animal");
ただし、ほとんどの場合、is
キーワードはまだ望んでいるものではありません。通常、オブジェクトが特定のタイプであることを知るだけでは不十分だからです。通常は、実際にそのオブジェクトをその型のインスタンスとして使用する必要があるため、キャストも必要です。そのため、次のようなコードを記述している可能性があります。
if(o is Animal)
((Animal)o).Speak();
ただし、これによりCLRはオブジェクトのタイプを最大2回チェックします。is
演算子を満足させるために1回チェックし、o
実際にである場合はAnimal
、キャストを検証するためにもう一度チェックします。
代わりにこれを行う方が効率的です。
Animal a = o as Animal;
if(a != null)
a.Speak();
as
オペレータは、それが代わりに返し、失敗した場合に例外をスローしませんキャストですnull
。このように、CLRはオブジェクトの型を1回だけチェックし、その後は、より効率的なnullチェックを実行するだけで済みます。
ただし、注意してください。多くの人がで罠に陥りas
ます。例外をスローしないため、一部の人々はそれを「安全な」キャストと見なし、通常のキャストを避けて排他的に使用します。これにより、次のようなエラーが発生します。
(o as Animal).Speak();
この場合、開発者はそれo
が常にであることを明確に想定してAnimal
おり、その想定が正しい限り、すべてが正常に機能します。しかし、それらが間違っている場合、それらがここで終わるのはNullReferenceException
です。通常のキャストでは、InvalidCastException
代わりに彼らが問題をより正確に特定していたはずです。
時々、このバグを見つけるのは難しいかもしれません:
class Foo{
readonly Animal animal;
public Foo(object o){
animal = o as Animal;
}
public void Interact(){
animal.Speak();
}
}
これは、開発者が毎回であることo
を明らかに期待している別のケースですAnimal
が、as
キャストが使用されるコンストラクターでは明らかではありません。フィールドに確実に割り当てられることが期待されるInteract
メソッドに到達するまで、それは明らかではありませんanimal
。この場合、誤解を招く例外が発生するだけでなく、実際のエラーが発生したときよりもかなり遅くなるまで、例外がスローされません。
要約すれば:
オブジェクトがなんらかのタイプかどうかを知る必要があるだけなら、を使用してくださいis
。
オブジェクトを特定のタイプのインスタンスとして扱う必要があるが、オブジェクトがそのタイプであるかどうかがわからない場合は、を使用as
して確認しnull
ます。
オブジェクトを特定のタイプのインスタンスとして扱う必要があり、オブジェクトがそのタイプであることが想定されている場合は、通常のキャストを使用します。
as
!