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, oolan Dog, değil Animal. Ancak, sınıf IsAssignableFromyö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, isanahtar kelimenin eşdeğer davranışına sahip olursunuz . Bu nedenle, istediğiniz davranış buysa, isdaha 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, isanahtar 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. isOperatörü tatmin etmek için bir kez kontrol eder ve ogerç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();
asOperatö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 oher zaman bir olacağını varsayar Animalve 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, InvalidCastExceptionsorunu 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 obir olmaya Animalher zaman, ama bu yapıcı, belirgin olmayan asdöküm kullanılır. Alanın pozitif olarak atanması beklenen Interactyö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 asve 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!