[c#] 제네릭 유형의 값을 비교하는 방법은 무엇입니까?
제네릭 유형의 값을 어떻게 비교합니까?
최소한의 샘플로 줄였습니다.
public class Foo<T> where T : IComparable
{
private T _minimumValue = default(T);
public bool IsInRange(T value)
{
return (value >= _minimumValue); // <-- Error here
}
}
오류는 다음과 같습니다.
‘> =’연산자는 ‘T’및 ‘T’유형의 피연산자에 적용 할 수 없습니다.
도대체 뭐야!? T
이미 구속되고 IComparable
, 가치 유형 (에 제약 경우에도 where T: struct
), 우리는 여전히 연산자 중 하나를 적용 할 수 없습니다 <
, >
, <=
, >=
, ==
또는 !=
. (I는 관련된 그 해결 방법을 알고 Equals()
존재를 ==
하고 !=
있지만, 관계 연산자에 대한 도움말을하지 않습니다).
따라서 두 가지 질문이 있습니다.
- 이 이상한 행동을 관찰하는 이유 는 무엇 입니까? 어떻게하는 일반적인 유형의 값 비교에서 우리를 유지 알려진 수를
IComparable
? 일반 제약의 전체 목적을 어떻게 든 무너 뜨리지 않습니까? - 이 문제를 해결하거나 최소한 해결하려면 어떻게해야합니까?
(이 겉보기에 간단한 문제와 관련된 몇 가지 질문이 이미 있다는 것을 알고 있지만 스레드 중 어느 것도 철저하거나 실행 가능한 답변을 제공하지 않으므로 여기에 있습니다.)
답변
IComparable
>=
연산자에 과부하가 걸리지 않습니다 . 당신은 사용해야합니다
value.CompareTo(_minimumValue) >= 0
답변
연산자 오버로딩 문제
불행히도 인터페이스는 오버로드 된 연산자를 포함 할 수 없습니다. 컴파일러에 다음을 입력 해보십시오.
public interface IInequalityComaparable<T>
{
bool operator >(T lhs, T rhs);
bool operator >=(T lhs, T rhs);
bool operator <(T lhs, T rhs);
bool operator <=(T lhs, T rhs);
}
왜 그들이 이것을 허용하지 않았는지 모르겠지만 언어 정의가 복잡하고 사용자가 올바르게 구현하기 어려울 것이라고 생각합니다.
또는 디자이너가 남용 가능성을 좋아하지 않았습니다. 예를 들어, 일을 상상 >=
A의 비교 class MagicMrMeow
. 또는 class Matrix<T>
. 결과는 두 값에 대해 무엇을 의미합니까?; 특히 모호성이있을 수있는 경우?
공식적인 해결 방법
위의 인터페이스는 합법적이지 않으므로 문제를 해결할 수있는 IComparable<T>
인터페이스가 있습니다. 연산자를 구현하지 않고 하나의 메서드 만 노출합니다.int CompareTo(T other);
http://msdn.microsoft.com/en-us/library/4d7sx9hd.aspx 참조
int
결과 (a 유사한 실제로 트리 비트 또는 트라이 어림이다 Boolean
하지만 세 가지 상태로). 이 표는 결과의 의미를 설명합니다.
Value Meaning
Less than zero This object is less than
the object specified by the CompareTo method.
Zero This object is equal to the method parameter.
Greater than zero This object is greater than the method parameter.
해결 방법 사용
와 동등한 작업을 수행 value >= _minimumValue
하려면 대신 다음을 작성해야합니다.
value.CompareTo(_minimumValue) >= 0
답변
value
null 일 수 있으면 현재 답변이 실패 할 수 있습니다. 대신 다음과 같이 사용하십시오.
Comparer<T>.Default.Compare(value, _minimumValue) >= 0
답변
public bool IsInRange(T value)
{
return (value.CompareTo(_minimumValue) >= 0);
}
IComparable 제네릭으로 작업 할 때보다 작거나 큰 연산자는 모두 CompareTo 호출로 변환해야합니다. 어떤 연산자를 사용하든 동일한 순서로 비교되는 값을 유지하고 0과 비교하십시오. ( x <op> y
해진다 x.CompareTo(y) <op> 0
곳 <op>
이다 >
, >=
등)
또한 사용하는 일반 제약 조건은 where T : IComparable<T>
. IComparable은 그 자체로 객체를 어떤 것과도 비교할 수 있음을 의미하며, 동일한 유형의 다른 객체와 비교하는 것이 더 적절할 수 있습니다.
답변
value >= _minimValue
사용 Comparer
클래스 대신 :
public bool IsInRange(T value ) {
var result = Comparer<T>.Default.Compare(value, _minimumValue);
if ( result >= 0 ) { return true; }
else { return false; }
}
답변
다른 사람들이 언급했듯이 CompareTo 메서드를 명시 적으로 사용해야합니다. 연산자와 함께 인터페이스를 사용할 수없는 이유는 클래스가 명확한 순위없이 임의의 수의 인터페이스를 구현할 수 있기 때문입니다. “a = foo + 5;”라는 표현을 계산하려한다고 가정 해 보겠습니다. foo가 6 개의 인터페이스를 구현할 때 모두 정수 두 번째 인수로 연산자 “+”를 정의합니다. 운영자에게 어떤 인터페이스를 사용해야합니까?
클래스가 여러 인터페이스를 파생 할 수 있다는 사실은 인터페이스를 매우 강력하게 만듭니다. 안타깝게도, 실제로하고 싶은 일에 대해 더 분명하게해야하는 경우가 많습니다.
답변
IComparable
라는 함수 만 강제합니다 CompareTo()
. 따라서 언급 한 연산자를 적용 할 수 없습니다.