2011-04-05 3 views
4

이 질문에서 오는 why does n.GetHashCode() work but n.GetType() throws and exception? Jon이 준 답변은 다음과 같은 질문을하게됩니다. Nullable<>GetType를 숨기지 않는 이유는 무엇입니까?Nullable <>이 GetType을 숨기지 않는 이유는 무엇입니까?

public new Type GetType() 
{ 
    return GetValueOrDefault().GetType(); 
} 

그러면이

int? i = null; 
Console.WriteLine(i.GetType().Name); 

이 작동해야합니까? 나는 명백한 것을 놓치고 있는가? 주의 사항은 무엇입니까? 나는 구글을 시도했지만 만족스러운 설명을 찾지 못했습니다.

업데이트 : 명확히하기 위해 : 조금. 이것은 작동합니다 : GetType

int? i = null; 
Console.WriteLine(i.GetHashCode()); 

i.GetType()이 가상이 아니며 무시할 수 없기 때문에 i.GetType()이 던지는 유일한 이유는 다음과 같습니다. 그래서 그것을 호출하면 inull을 결과로 던진 객체로 상자에 넣습니다. 그러나 Nullable가 다음과 같이 구현 될 경우

 public struct Nullable<T> where T : struct 
{ 
    .... 
    public new Type GetType() 
    { 
     return GetValueOrDefault().GetType(); 
    } 
} 

그러면 처음 두 호출 대신이 모든 것이 작동한다는 점에서 동작이보다 일관성있게 유지됩니다 (imho).

 int? i = null; 
Console.WriteLine(i.GetHashCode()); 
Console.WriteLine(i.ToString()); 
Console.WriteLine(i.GetType()); 
+2

'Object'에서 상속 한 메소드를 어떻게 숨길 수 있습니까? – Kevin

+1

게다가, 왜 당신은하고 싶습니까? –

+3

네, 참으로 왜 'null.GetType()'이 null 참조 예외를 던지겠습니까 :) – Poma

답변

2

GetType이 현재 런타임 유형의 정확한 인스턴스를 반환하기 때문이라고 생각합니다. 이 경우 null을 참조하기 때문에 런타임 유형이 없습니다.

MyBaseClass myBase = null; 
    MyDerivedClass myDerived = null; 
    object o = myDerived; 
    MyBaseClass b = myDerived; 

myBase.GetType() 경우 MyBaseClass 반환 및 myDerived.GetType()MyDerivedClass을 반환 한 후 무엇을 o.GetType()b.GetType() 반환해야합니다 :

이 예제를 고려? 이 GetType의 계약을 깰 때문에

단순히 object.GetType을 숨기고 null 때의 컴파일 시간 유형을 반환하지 않는 이유 Nullable, 아마.

+0

'int?'는'Nullable '과 동일하며'Nullable '에'GetType'을 호출하면'typeof (T)'를 반환합니다. 그것은 기존의 행동입니다. – ChrisWue

+0

@ChrisWue 아니요 typeof (T)를 반환하지 않습니다.'object'에서 상속 된'GetType'을 호출하고 런타임 유형을 반환합니다. 참조 : http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx. 어쩌면 당신은'Type.GetType'과 혼동을 느낍니까? –

+0

좋아, 어쩌면 내가 옳지 않은 표현 일지 모르지만'GetType'은'Nullable '에서 호출 될 때 기본 유형을 반환합니다. – ChrisWue

0

나는 왜 그렇게하지 않았던가하는 이유는 같은 이름과 서명을 가진 new 메서드를 사용하여 상속 된 메서드를 숨기는 것이 일반적으로 좋지 않다는 것입니다.

경우 그들은 그들이 Nullable<T> 구조체, 또는 기본 유형의 유형을 반환해야하는 경우 문제는, 실제로 Object.GetType()을 숨길하기로 결정했습니다.이 중 하나가 될 것입니다 :

public struct Nullable<T> where T : struct 
{ 
    .... 
    public new Type GetType() 
    { 
     return typeof(Nullable<T>); 
    } 
} 

나 :

public struct Nullable<T> where T : struct 
{ 
    .... 
    public new Type GetType() 
    { 
     return typeof(T); 
    } 
} 

이있는 경우 :

int? i = null; 

또는 :

int? i = 42; 

i의 "진짜"실행시의 형태는 확실히 Nullable<int> (int?라고도 알려져 있음). 물론 Nullable<int>을 반환 한 GetType 메서드를 새로 도입하면 (.NET 버전 5.0에서 말합니다) 큰 변화가 생깁니다. 오늘날 방식에서, inull 참조 또는 때문에 Nullable<>의 마법 권투의 박스 int (박스형 Nullable<int>하지) 중 하나에 박스 될 것 때문이다.

그러나 그는 실제 유형을 알고 있기 때문에 컴파일시의 형태T?의 적 변수에 .GetType()를 사용하는 (수) 프로그래머 (또는 다른 표현)에 대한 이유는 정말 없다 컴파일 시간 유형, 즉 typeof(T?)과 동일합니다. 또한 기본 유형이 typeof(T)임을 알고 있습니다. 컴파일시의 형태가 T 때 프로그래머가 .GetType()를 사용하는 그는 알고 있기 때문에 (null 허용되지 않음) "보통의"값 유형 T에 대해 같은 이유로

은, 그것이 유용하지 않습니다 결과는 항상 것입니다 typeof(T)이되어야합니다. 이는 모든 값 유형이 봉인 된 유형이기 때문입니다. 또한, 봉인 된 참조 유형 (형식 매개 변수가 공역 또는 반 행위가 아닌)의 경우 .GetType()은 쓸모가 없습니다.

string str = ...; 
... 
var t = str.GetType(); // This is really useless. If str is null 
         // an exception is thrown. Otherwise the 
         // t will ALWAYS be typeof(string) because 
         // the class System.String is a sealed class. 

Nullable<> 구조체의 기본 클래스는 System.ValueTypeSystem.Object 있으며 Nullable<> 더 인터페이스를 구현 아니오

는 예를 제공한다. 그러나 이전에 우리의 i이 캐스팅되어 있고 컴파일시 유형이 ValueType 또는 object (또는 dynamic) 인 변수에 넣을 경우 인 ID가 Nullable<int>이며 일반 박스형 값 유형이됩니다. 따라서 Object.GetType()이 만들어진 경우에도 (물론 매우 위험 할 수 있습니다) virtual은 도움이되지 않습니다.

결론 : 컴파일 유형이 Nullable<> 인 경우에만 런타임 유형이 Nullable<>이므로이 "문제"를 수정하는 것은 흥미롭지 않습니다.

관련 문제