제네릭 유형의 값을 비교하는 방법은 무엇입니까?
제네릭 유형의 값을 어떻게 비교합니까?
최소 샘플로 줄였습니다.
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; }
}
As others have stated, one needs to explicitly use the CompareTo method. The reason that one cannot use interfaces with operators is that it is possible for a class to implement an arbitrary number of interfaces, with no clear ranking among them. Suppose one tried to compute the expression "a = foo + 5;" when foo implemented six interfaces all of which define an operator "+" with an integer second argument; which interface should be used for the operator?
The fact that classes can derive multiple interfaces makes interfaces very powerful. Unfortunately, it often forces one to be more explicit about what one actually wants to do.
IComparable
only forces a function called CompareTo()
. So you cannot apply any of the operators that you have mentioned
I was able to use Peter Hedburg's answer to create some overloaded extension methods for generics. Note that the CompareTo
method doesn't work here, as type T
is unknown and doesn't present that interface. That said, I'm interested in seeing any alternatives.
I would like to have posted in C#, but Telerik's converter fails on this code. I'm not familiar enough with C# to reliably convert it manually. If someone would like to do the honors, I'd be pleased to see this edited accordingly.
<Extension>
<DebuggerStepThrough>
Public Sub RemoveDuplicates(Of T)(Instance As List(Of T))
Instance.RemoveDuplicates(Function(X, Y) Comparer(Of T).Default.Compare(X, Y))
End Sub
<Extension>
<DebuggerStepThrough>
Public Sub RemoveDuplicates(Of T)(Instance As List(Of T), Comparison As Comparison(Of T))
Instance.RemoveDuplicates(New List(Of Comparison(Of T)) From {Comparison})
End Sub
<Extension>
<DebuggerStepThrough>
Public Sub RemoveDuplicates(Of T)(Instance As List(Of T), Comparisons As List(Of Comparison(Of T)))
Dim oResults As New List(Of Boolean)
For i As Integer = 0 To Instance.Count - 1
For j As Integer = Instance.Count - 1 To i + 1 Step -1
oResults.Clear()
For Each oComparison As Comparison(Of T) In Comparisons
oResults.Add(oComparison(Instance(i), Instance(j)) = 0)
Next oComparison
If oResults.Any(Function(R) R) Then
Instance.RemoveAt(j)
End If
Next j
Next i
End Sub
--EDIT--
I was able to clean this up by constraining T
to IComparable(Of T)
on all methods, as indicated by OP. Note that this constraint requires type T
to implement IComparable(Of <type>)
as well.
<Extension>
<DebuggerStepThrough>
Public Sub RemoveDuplicates(Of T As IComparable(Of T))(Instance As List(Of T))
Instance.RemoveDuplicates(Function(X, Y) X.CompareTo(Y))
End Sub
참고URL : https://stackoverflow.com/questions/6480577/how-to-compare-values-of-generic-types
'IT박스' 카테고리의 다른 글
JList 요소에 대한 두 번 클릭 이벤트 (0) | 2020.11.04 |
---|---|
jquery 직렬화를 사용하여 파일 업로드를 수행하는 방법 (0) | 2020.11.04 |
JavaScript의 스크립트 태그에서 JSON을 어떻게 읽을 수 있습니까? (0) | 2020.11.04 |
MySQL : 최신 기록 가져 오기 (0) | 2020.11.04 |
널 포인터가 모든 비트가 0이 아닐 때 C / C ++ 코드를 올바르게 작성하는 방법 (0) | 2020.11.04 |