Saturday, February 19, 2011

Why Type.Equals(t1, t2) and not the equality operator?

Why must Type.Equals(t1, t2) be used to determine equivalent types, and not the equality operator (e.g. for VB.NET, t1 = t2)?

It seems inconsistent with other parts of the .NET API.

Example in VB.NET:

If GetType(String) = GetType(String) Then Debug.Print("The same, of course") End If

causes a compile-time error of "Operator '=' is not defined for types 'System.Type' and 'System.Type'."

From stackoverflow
  • Given the way types are loaded, that surprises me. Where did you hear this from?

    The docs for System.Type.Equals(Type) suggest that it's comparing via the UnderlyingSystemType property, but I'm not sure under what circumstances two different Type objects would have the same underlying system type.

    I'd be really interested to see an example where this mattered... my guess is that from anywhere in "user code" they'll be the same thing, but there may be some cunning BCL code where it matters.

  • Looking at the source code in Reflector, I can't see how Type.Equals(t1,t2) would be handled any differently than t1 = t2. (There is actually no Type.Equals; it will actually call Object.Equals).

    In C#, T1 == T2 works just fine.

    Jon Skeet : No, Type does override Equals, as far as I can see... at least in .NET 3.5.
    James Curran : It overrides Type.Equals(Type), but not Equals(Type, Type) which is the one the oper== would be mapped to, hence the relevant one here.
  • According to this, the VB equality operator does a value comparison, not a reference comparison. Using Type.Equals(t1,t2) forces it to do reference comparison. If t1 and t2 are types, I would think that either would work, but I'm a C# guy so what do I know. I'd probably prefer using the is syntax for known classes and IsInstanceOf, if I don't care about exact type match.

    Typeof a Is Boolean
    
    a.GetType().IsAssignableFrom( b.GetType() )
    
    Olmo : IsInstanceOf is not a method from GetType. There's however IsInstanceOfType but takes an object (not a type) as the argument and is meant to be used like this: typeof(int).IsInstanceOfType(3). I thing what you want is IsAssignableFrom that is meant to be used like this: typeof(Animal).IsAssignaleFrom(typeof(Leon)
    tvanfosson : You're probably right -- I think I was originally thinking exact type equality (and simply put in an extra GetType()). AssignableFrom works better for non-exact matching, though.
  • In VB.NET The Is is the language operator used to test type equality. Note that Type.Equals test whether two variable of the same type are pointed to the same object. As shown by the below example.

    Public Class Form1
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim X As New TestObject
            Dim Y As New TestObject
    
            If X Is Y Then MsgBox("The Same 1")
            If Type.Equals(X, Y) Then MsgBox("The Same 2")
    
            X = Y
            If X Is Y Then MsgBox("The Same 3")
    
            If Type.Equals(X, Y) Then MsgBox("The Same 4")
        End Sub
    End Class
    
    Public Class TestObject
        Public Value As Double
    End Class
    

    This was done because the history of the 'equals' operator in the BASIC language. When Objects were introduced in VB4 IS was chosen to test for equality as it was felt that overloading equals would be problematic.

    I suggest searching google and usenet for Paul Vicks comments on why some individual BASIC idioms were ported and why other were not. I believe in this case was to avoid confusion as VB.NET introduced

    ObjectA = ObjectC 'which causes ObjectA to reference the same objects as referenced by ObjectC.

    While in VB6 it was Set ObjectA = ObjectC

    The same reason why when objects were introduced in VB4 IS and Set were used to deal with object instead of overloading equals.

    Ultimately these quirks became part of the the Basic Way of coding.

0 comments:

Post a Comment