Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# contains object not working

Tags:

c#

list

contains

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 :-)

like image 694
Mansa Avatar asked Dec 11 '25 14:12

Mansa


1 Answers

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:

    • What is the best algorithm for an overridden System.Object.GetHashCode?
    • Guidelines for Overriding Equals()
  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:

  • What is the difference between a Field and a Property in C#?
  • Public Fields versus Automatic Properties

And last have a look at naming conventions for C#

like image 84
Gilad Green Avatar answered Dec 14 '25 04:12

Gilad Green



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!