Teejay
Teejay

Reputation: 7481

Comparing with Nothing is not the same of comparing with a variable containing Nothing

I have this strange behavior of VB.

I need to check if a SingleOrDefault() on a KeyValuePair collection found what I was searching for.

So:

Dim revProp As KeyValuePair(Of IKeyInterfaceType, IValueInterfaceType) = 
                                 revisionProperties.SingleOrDefault(Function(kvp) ...)

In C# I would then write:

if (revProp.Equals(default(KeyValuePair<IKeyInterfaceType,IValueInterfaceType>)))

Nothing is the VB equivalent for C#'s default, in fact if I write

Dim emptyRevProp As KeyValuePair(Of IKeyInterfaceType, IValueInterfaceType) = Nothing

and then look at emptyRevProp in QuickWatch, I see a KeyValuePair with null key and value.

If I then compare the two structs with Equals:

revProp.Equals(emptyRevProp)

I correctly get True if SingleOrDefault() found nothing in the collection satisfying supplied condition.

But, here it comes the matter, if I write:

revProp.Equals(Nothing)

I get False.

Why is this?

Upvotes: 0

Views: 1066

Answers (1)

Tim Schmelter
Tim Schmelter

Reputation: 460208

In VB.NET Nothing can be null or default. In this case it's just treated as null/Nothing. But Nothing is not KeyValuePair(Of IKeyInterfaceType, IValueInterfaceType). Therefore ValueType.Equals(which overrides Object.Equals) returns False. The argument is not the correct type, so it cannot be equal. From MSDN:

true if obj and this instance are the same type and represent the same value; otherwise, false.

The source is even more clear:

public override bool Equals (Object obj) {
    if (null==obj) {
        return false;  // <---- !!!!!!!!!
    }
    RuntimeType thisType = (RuntimeType)this.GetType();
    RuntimeType thatType = (RuntimeType)obj.GetType();

    if (thatType!=thisType) {
        return false;
    }

    // omitting value comparison  ...
}

When you use

revProp.Equals(emptyRevProp)

It can compare the values with each other, hence it returns true.

You could use Nothing as default in this way:

revProp.Equals(CType(Nothing, KeyValuePair(Of IKeyInterfaceType, IValueInterfaceType)))

But that would be less readable than declaring it as the correct type in the first place.

Upvotes: 2

Related Questions