이 문제에 대해 자세히 설명 하는 Microsoft Connect 기사 를 찾을 수있었습니다 .
불행히도이 동작은 의도적으로 설계된 동작이며 값 형식을 포함 할 수있는 형식 매개 변수와 함께 사용할 수있는 쉬운 솔루션은 없습니다.
유형이 참조 유형으로 알려진 경우, 객체에 정의 된 기본 과부하는 변수가 참조 동등성을 테스트하지만 유형에 따라 자체 사용자 정의 과부하가 지정 될 수 있습니다. 컴파일러는 변수의 정적 유형에 따라 사용할 과부하를 결정합니다 (결정은 다형성이 아님). 따라서 제네릭 형식 매개 변수 T를 봉인되지 않은 참조 형식 (예 : 예외)으로 제한하도록 예제를 변경하면 컴파일러에서 사용할 특정 오버로드를 결정할 수 있으며 다음 코드는 컴파일됩니다.
public class Test<T> where T : Exception
유형이 값 유형으로 알려진 경우 사용 된 정확한 유형을 기반으로 특정 값 평등 테스트를 수행합니다. 참조 유형 비교는 값 유형에 의미가 없으며 컴파일러가 어떤 특정 값 비교를 수행 할 수 있는지 알 수 없기 때문에 여기서 "기본"비교는 적절하지 않습니다. 컴파일러는 ValueType.Equals (Object)를 호출 할 수 있지만이 방법은 리플렉션을 사용하며 특정 값 비교에 비해 상당히 비효율적입니다. 따라서 T에 값 유형 제약 조건을 지정하더라도 컴파일러가 여기에서 생성하는 것은 합리적이지 않습니다.
public class Test<T> where T : struct
제시 한 경우, 컴파일러가 T가 값인지 참조 유형인지조차 알지 못하는 경우, 가능한 모든 유형에 유효한 것을 생성 할 것은 없습니다. 참조 비교는 값 유형에 유효하지 않으며 일부 종류의 값 비교는 과부하되지 않은 참조 유형에 대해서는 예상치 못한 것입니다.
여기 당신이 할 수있는 일이 있습니다 ...
이 두 가지 방법이 참조 및 값 유형의 일반적인 비교에 효과적이라는 것을 확인했습니다.
object.Equals(param, default(T))
또는
EqualityComparer<T>.Default.Equals(param, default(T))
"=="연산자와 비교하려면 다음 방법 중 하나를 사용해야합니다.
T의 모든 사례가 알려진 기본 클래스에서 파생 된 경우 일반 유형 제한을 사용하여 컴파일러에 알릴 수 있습니다.
public void MyMethod<T>(T myArgument) where T : MyBase
그런 다음 컴파일러는 작업을 수행하는 방법을 인식 MyBase
하고 현재보고있는 'T'및 'T'유형의 피연산자에 '운영자'== '를 적용 할 수 없습니다.
또 다른 옵션은 T를 구현하는 모든 유형으로 제한하는 것 IComparable
입니다.
public void MyMethod<T>(T myArgument) where T : IComparable
그런 다음 IComparable 인터페이스에서CompareTo
정의한 메소드 를 사용하십시오 .
if (myArgument?.Equals( default(T) ) != null )
.