C# List comparison between custom objects

Pair<BoardLocation, BoardLocation> loc = new Pair<BoardLocation, BoardLocation>( this.getLocation(), l );
if(!this.getPlayer().getMoves().Contains( loc )) {
    this.getPlayer().addMove( loc );
}

I'm using a Type I have created called "Pair" but, I'm trying to use the contains function in C# that would compare the two types but, I have used override in the Type "Pair" itself to compare the "ToString()" of both Pair objects being compared. So there are 4 strings being compared. The two Keys and two value. If the two Keys are equal, then the two values are compared. The reason why this makes sense is the Key is the originating(key) location for the location(value) being attacked. If the key and value are the same then the object should not be added.

public override bool Equals( object obj ) {
    Pair<K, V> objNode = (Pair<K, V>)obj;
    if(this.value.ToString().CompareTo( objNode.value.ToString() ) == 0) {
        if(this.key.ToString().CompareTo( objNode.key.ToString() ) == 0) {
            return true;
        } else
            return false;
    } else {
        return false;
    }
}

The question is, Is there a better way to do this that doesn't involve stupid amounts of code or creating new objects for dealing with this. Of course if any ideas involve these, I am all ears. The part that confuses me about this is, perhaps I dont understand what is going on but, I was hoping that C# offered a method that just equivalence of values and not the object memory locations and etc.

I've just ported this from Java as well, and it works exactly the same but, I'm asking this question for C# because I'm hoping there was a better way for me to compare these objects without using ToString() with generic Types.

Jon Skeet
people
quotationmark

You can definitely make this code a lot simpler by using && and just returning the value of equality comparisons, instead of all those if statements and return true; or return false; statements.

public override bool Equals (object obj) {
    // Safety first: handle the case where the other object isn't
    // of the same type, or obj is null. In both cases we should
    // return false, rather than throwing an exception
    Pair<K, V> otherPair = objNode as Pair<K, V>;
    if (otherPair == null) {
        return false;
    }

    return key.ToString() == otherPair.key.ToString() &&
        value.ToString() == otherPair.value.ToString();
}

In Java you could use equals rather than compareTo.

Note that these aren't exactly the same as == (and Equals) use an ordinal comparison rather than a culture-sensitive one - but I suspect that's what you want anyway.

I would personally shy away from comparing the values by ToString() representations. I would use the natural equality comparisons of the key and value types instead:

public override bool Equals (object obj) {
    // Safety first: handle the case where the other object isn't
    // of the same type, or obj is null. In both cases we should
    // return false, rather than throwing an exception
    Pair<K, V> otherPair = objNode as Pair<K, V>;
    if (otherPair == null) {
        return false;
    }

    return EqualityComparer<K>.Default.Equals(key, otherPair.key) &&
        EqualityComparer<K>.Default.Equals(value, otherPair.value);
}

(As Avner notes, you could just use Tuple of course...)

As noted in comments, I'd also strongly recommend that you start using properties and C# naming conventions, e.g.:

if (!Player.Moves.Contains(loc)) {
    Player.AddMove(loc);
}

people

See more on this question at Stackoverflow