.netvb.netgenericsmathvs-error

A call to a generic function (with constraints implemented with an interface) produces an error about missing constraints. What do I fail to see?


I want to do some arithmetic addition in my generic class with some constraints in place. For brevity, assume there is just one public member named Value.

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

    '(1) filled in below
End Class

Outside the class, I have an interface and a structure implementing it as follows:

Public Interface IAddable(Of U As {Structure, IComparable})
    Function Add(a As U, b As U) As U
End Interface

Public Structure Int64Calculator
    Implements IAddable(Of Int64)

    Public Function Add(ByVal a As Int64, ByVal b As Int64) As Int64 _
        Implements IAddable(Of Int64).Add
        Return a + b
    End Function
End Structure

This enables me to create a function in my class at position marked (1) above. There are some constraints, but as far as I can tell, I think I got that part right. New on C is needed, otherwise As C = New C() would not be possible.

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

    '(2) filled in below

    Private Function Add(Of U As {Structure, IComparable},
                            C As {IAddable(Of U), New}) _
                        (ByVal a As U, ByVal b As U) As U

        Dim calc As C = New C()
        Return calc.Add(a, b)
    End Function
End Class

Now I intended to use this function to do calculations in the class' overridden GetHashCode function, as follows:

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

    Public Overrides Function GetHashCode() As Integer
        Const HASHPRIME_1 As Int64 = 4294967291    '32 bits.
        Dim lCompHash As Int64          'Partial hash for actual component.

        lCompHash = Add(Of T, Int64Calculator)(Value, HASHPRIME_1)
    End Function

    '... as above
End Class

However, VS complains with error BC32044, the squiggly underlines referring to

Add(Of T, Int64Calculator)

stating

"Type argument 'Int64Calculator' does not inherit from or implement the constraint type 'IAddable(Of T As {Structure, IComparable})'".

Only that I think that the structure Int64Calculator does implement that constraint indeed via Implements IAddable(Of Int64).

What do I miss?


Solution

  • Part 1:
    As @Gserg commented:
    GenericInterval does not enforce T to be Int64. So at the point when Int64Calculator is tested for validity, it is required to handle any T as {Structure, IComparable}, not just Int64. You can fix that with lCompHash = Me.Add(Of Int64, Int64Calculator)(Me.Value, HASHPRIME_1), but then you'll have another error about Me.Value not necessarily being convertable to Int64.

    Part 2:
    This simplest way to implement GetHashCode for the case where you consider objects as equal based on certain properties is to use Tuple.Create(x,y).GetHashCode()

    For example, if you consider properties equal that have the same Name and PhoneNumber properties, then the following code would return a usable HashCode.

    public override int GetHashCode() { return Tuple.Create(Name, PhoneNumber).GetHashCode(); }