Mansa Mansa - 3 years ago 197
C# Question

c# contains object not working

I am trying to create a check between lists, but am having no luck :-/

I have a game board with 100 fields and make this loop to add only empty fields into a new list:

for(int i = 0; i < thisGame.boardFields.Count; i++)
{
if (thisGame.boardFields.Count != 0 && thisGame.boardFields [i] != null)
{
BoardField thisField = thisGame.boardFields [i];
if (thisField.owner == "0" && thisField.number != 13)
{
Tile tTile = new Tile();
tTile.color = thisField.color;
tTile.number = thisField.number.ToString();

tempBoard.Add (tTile);
}
}
}


Then I loop through the players 5 tiles to see if the player has a tile which is not playable, e.g. a empty field with the same object is not available like this:

for (var i = 0; i < thisGame.playerTiles.Count; i++)
{
Tile tempTile = new Tile();
tempTile.color = thisGame.playerTiles[i].color;
tempTile.number = thisGame.playerTiles[i].number.ToString();

if (!tempBoard.Contains (tempTile))
{
testTile = tempTile;
print ("HUSTON WE HAVE A PROBLEM: " + tempTile.color + "-" + tempTile.number);
}
}


This is the definition of the Tile class:

public class Tile
{
public int id;
public string color;
public string number;
}


Now my problem is, that it prints on every 5 tiles in the players tile list? All tiles in the players tile list is available in the
tempBoard
list?

What am I missing her?

Hoping for help and thanks in advance :-)

Answer Source

To work Contains needs to check equality between two objects. By default, for reference types it does it by checking reference equality. Therefore, having two different instances (objects in memory) of same type and with same values to all properties will still result in them being not equal, and for Contains to return false.

To overcome this 3 options:

  1. you need your class to override the Equals and GetHashCode methods of object. References on overriding the methods:

  2. Another option instead of overriding the methods in your class is to create a class implementing the IEquatable<Tile> interface and then use the overload:

    list.Contains(searchedTile, new SomeClassImplementingInterface());
    

    Id use this in case the overriding of the Equals/GetHashCode are non-trivial (do not include all properties of the class) or if you do not have control over the Tile class.

  3. Use linq's Any method:

    collection.Any(item => item.number == tempTile.number && item.color == temTile.color);
    

Also, it is nice to initialize your objects using the object initializer syntax:

Tile tTile = new Tile
{ 
    color = thisField.color,
    number = thisField.number.ToString()
}

And if you have your fields public they should probably be defined as properties:

public class Tile 
{
    public int Id { get; set; }
    public string Color { get; set; }
    public string Number { get; set; }
}

About properties vs fields:

And last have a look at naming conventions for C#

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download