Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Bu bir hatadır. C # 'daki typeof işleci yalnızca nesne adlarını alabilir, nesneleri değil.
if (obj1.GetType() == typeof(int))
// Some code here
Bu işe yarayacak, ama beklediğiniz gibi olmayabilir. Burada gösterildiği gibi değer türleri için kabul edilebilir, ancak referans türleri için, tür yalnızca miras hiyerarşisinde başka bir şey değil , tam olarak aynı türdeyse true değerini döndürür . Örneğin:
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");
}
Bu basacaktır "o is something else"
tipi nedeniyle, o
olan Dog
, değil Animal
. Ancak, sınıf IsAssignableFrom
yöntemini kullanırsanız bu işlemi yapabilirsiniz Type
.
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
Yine de bu teknik hala büyük bir sorun bırakıyor. Değişkeniniz null ise, çağrısı GetType()
bir NullReferenceException özel durumu oluşturur. Böylece, düzgün çalışmasını sağlamak için:
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
Bununla, is
anahtar kelimenin eşdeğer davranışına sahip olursunuz . Bu nedenle, istediğiniz davranış buysa, is
daha okunabilir ve daha verimli olan anahtar kelimeyi kullanmalısınız .
if(o is Animal)
Console.WriteLine("o is an animal");
Bununla birlikte, çoğu durumda, is
anahtar kelime hala gerçekten istediğiniz şey değildir, çünkü genellikle bir nesnenin belirli bir türde olduğunu bilmek yeterli değildir. Genellikle, o nesneyi, bu türün bir örneği olarak kullanmak istersiniz , bu da onu döküm gerektirir. Ve böylece kendinizi böyle kod yazarken bulabilirsiniz:
if(o is Animal)
((Animal)o).Speak();
Ancak bu, CLR'nin nesnenin türünü iki kez kontrol etmesini sağlar. is
Operatörü tatmin etmek için bir kez kontrol eder ve o
gerçekten bir ise Animal
, almayı doğrulamak için tekrar kontrol ederiz.
Bunun yerine bunu yapmak daha verimlidir:
Animal a = o as Animal;
if(a != null)
a.Speak();
as
Operatör, yerine dönen başarısız olursa bir istisna olmayacak bir döküm olduğununull
. Bu şekilde, CLR nesnenin türünü sadece bir kez kontrol eder ve bundan sonra, daha verimli olan bir boş kontrol yapmamız gerekir.
Ama dikkat: birçok insan ile bir tuzağa düşer as
. İstisnalar atmadığından, bazı insanlar bunu "güvenli" bir oyuncu olarak düşünür ve sadece düzenli olarak atmalarını sağlar. Bu, aşağıdaki gibi hatalara yol açar:
(o as Animal).Speak();
Bu durumda, geliştirici bunun o
her zaman bir olacağını varsayar Animal
ve varsayımları doğru olduğu sürece her şey iyi çalışır. Ama eğer yanılıyorlarsa, o zaman burada neyle sonuçlanırlar NullReferenceException
? Düzenli bir oyuncu kadrosuyla, InvalidCastException
sorunu daha doğru bir şekilde tanımlayacak bir yer alacaklardı.
Bazen, bu hatayı bulmak zor olabilir:
class Foo{
readonly Animal animal;
public Foo(object o){
animal = o as Animal;
}
public void Interact(){
animal.Speak();
}
}
Bu geliştirici açıkça bekliyor başka bir durumdur o
bir olmaya Animal
her zaman, ama bu yapıcı, belirgin olmayan as
döküm kullanılır. Alanın pozitif olarak atanması beklenen Interact
yönteme ulaşana kadar açık değildir animal
. Bu durumda, sadece yanıltıcı bir istisna elde etmekle kalmaz, aynı zamanda gerçek hatanın ortaya çıkmasından çok daha sonraya kadar atılmaz.
Özetle:
Yalnızca bir nesnenin bir tür olup olmadığını bilmeniz gerekiyorsa kullanın is
.
Bir nesneyi belirli bir türün örneği olarak ele almanız gerekiyorsa, ancak nesnenin bu türden olacağından emin değilseniz, kullanın as
ve kontrol edin null
.
Bir nesneyi belirli bir türün örneği olarak ele almanız gerekiyorsa ve nesnenin bu türden olması gerekiyorsa, normal bir döküm kullanın.
as
!