Search code examples
.netgenericsicomparable

Implementing IComparable<T> in Generics: how can I access the Generic's Value?


I have a generic class as follows (Value is Public only for the sake of simplicity, in reality, it's all encapsulated in properties):

Public MustInherit Class GenericInterval(Of T As {Structure, IComparable})
    Public Value As T                     
End Class

I want to implement IComparable(Of T):

Public MustInherit Class GenericInterval(Of T As {Structure, IComparable})
    Implements IComparable(Of T)

    Public Value As T                     

    Public Function CompareTo(Other As T) As Int32 Implements IComparable(Of T).CompareTo
        Return Value.CompareTo(Other)
    End Function
End Class

But is this really correct? It feels somewhat "unmatching", as if I'd compare a value with a generic type.

In a test module I instantiate 2 variables and assign them values.

Dim lTest1 As New GenericInterval()
Dim lTest2 As New GenericInterval()

lTest1.Value = 4
lTest2.Value = 5

Now I'd expect to compare lTest1 with lTest2. However, I need to perform the test on the extracted Value:

If lTest1.CompareTo(lTest2.Value) >= 0 Then
End If

But by doing so, I could as well just use

If lTest1.Value >= lTest2.Value Then ...

omiting the interface altogether.

Wouldn't it be advantageous to allow me to access Value already in the generic CompareTo, such:

Return Value.CompareTo(Other.Value)

However, Value is not an accessible member in the generic.

Do I miss something here, or is this unaccessibility by design? If so, what is the purpose?


Solution

  • You need to implement IComparable(Of GenericInterval(Of T))

    Public Class GenericInterval(Of T As {Structure, IComparable})
        Implements IComparable(Of GenericInterval(Of T))
    
        Public Sub New(value As T)
            Me.Value = value
        End Sub
    
        Public Readonly Value As T
    
        Public Function CompareTo(other As GenericInterval(Of T)) As Integer Implements IComparable(Of GenericInterval(Of T)).CompareTo
            Return Value.CompareTo(other.Value)
        End Function
    End Class
    

    Test:

    Sub Main
        Dim lTest1 As New GenericInterval(Of Integer)(4)
        Dim lTest2 As New GenericInterval(Of Integer)(5)
    
        Console.WriteLine(lTest2.CompareTo(lTest1))
    End Sub
    

    If T is Structure and Value only property you might want to turn GenericInterval into a structure also. (it would need to be immutable)