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은 객체 유형을 최대 두 번 확인합니다. is
연산자 를 만족시키기 위해 한 번 확인하고 o
실제로 인 경우 Animal
캐스트를 다시 확인합니다.
대신이 작업을 수행하는 것이 더 효율적입니다.
Animal a = o as Animal;
if(a != null)
a.Speak();
as
운영자는 대신 반환, 실패 할 경우 예외를 throw하지 않습니다 캐스트입니다 null
. 이런 식으로 CLR은 객체의 유형을 한 번만 확인한 다음 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
!