why the Clist.Contains(customer) is not getting true in that case ?

why the Clist.Contains(customer) is not getting true while the new object that i created is already on the list dose that means that i have to override the Equals method in the customer class
c#

List<Customer> Clist = new List<Customer>(2)
{
new Customer() { Id = 1, Name = "mina" },
new Customer() { Id = 2, Name = "shaker" },
new Customer() { Id = 3, Name = "Kirollos" },
new Customer() { Id = 4, Name = "georget" }
};

Customer customer = new Customer() { Id = 1, Name = "mina" };


if (Clist.Contains(customer))
{
Console.WriteLine("Customer Exits");
}
else
{
Console.WriteLine("customer is not in the list");
}
c#

List<Customer> Clist = new List<Customer>(2)
{
new Customer() { Id = 1, Name = "mina" },
new Customer() { Id = 2, Name = "shaker" },
new Customer() { Id = 3, Name = "Kirollos" },
new Customer() { Id = 4, Name = "georget" }
};

Customer customer = new Customer() { Id = 1, Name = "mina" };


if (Clist.Contains(customer))
{
Console.WriteLine("Customer Exits");
}
else
{
Console.WriteLine("customer is not in the list");
}
i have tried to override the Equals() method in the customer class but, what was intersting is that it works
c#
public class Customer
{
public int Id { get; set; }
public string? Name { get; set; }

public override bool Equals(object? obj)
{
if (obj == null) return false;
if (obj.GetType() != typeof(Customer)) return false;
return (this.Name == ((Customer)obj).Name && this.Id == ((Customer)obj).Id);
}

public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}
c#
public class Customer
{
public int Id { get; set; }
public string? Name { get; set; }

public override bool Equals(object? obj)
{
if (obj == null) return false;
if (obj.GetType() != typeof(Customer)) return false;
return (this.Name == ((Customer)obj).Name && this.Id == ((Customer)obj).Id);
}

public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}
20 Replies
mtreit
mtreit5mo ago
Yes you need to implement value semantics (Equals, and likely you want GetHashCode too) The easy way is to just use a record instead of a class and the compiler will implement all of that for you.
steven preadly
steven preadlyOP5mo ago
i did not get this can you explain
mtreit
mtreit5mo ago
public record Customer(int Id, string Name);
mtreit
mtreit5mo ago
Classes by default use reference semantics meaning comparing them for equality just checks if the variables point to the same instance in memory. So if you want to compare them based on the data they contain, you need to implement value semantics: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type
How to define value equality for a class or struct - C#
Learn how to define value equality for a class or struct. See code examples and view available resources.
mtreit
mtreit5mo ago
Yes, that's the way to fix it.
steven preadly
steven preadlyOP5mo ago
record is a type that are different than class
Angius
Angius5mo ago
Record is a type with value equality built-in C# has two types of objects: value types and reference types Value types are compared by their... values. Reference types, by their references
struct VFoo
{
public int Bar { get; set; }
}

class RFoo
{
public int Bar { get; set; }
}

var a = new VFoo { Bar = 1 };
var b = new VFoo { Bar = 1 };

// this will be true, since both structs have the same values
Console.WriteLine(a == b);

var c = new RFoo { Bar = 1 };
var d = new RFoo { Bar = 1 };

// this will be false, since they reference different instances
Console.WriteLine(c == d);

// those will be true, since it's the same instance
Console.WriteLine(c == c);
Console.WriteLine(d == d);
struct VFoo
{
public int Bar { get; set; }
}

class RFoo
{
public int Bar { get; set; }
}

var a = new VFoo { Bar = 1 };
var b = new VFoo { Bar = 1 };

// this will be true, since both structs have the same values
Console.WriteLine(a == b);

var c = new RFoo { Bar = 1 };
var d = new RFoo { Bar = 1 };

// this will be false, since they reference different instances
Console.WriteLine(c == d);

// those will be true, since it's the same instance
Console.WriteLine(c == c);
Console.WriteLine(d == d);
steven preadly
steven preadlyOP5mo ago
yes i understand this that`s why i override the Equals up there , but record can be a struct or a class this means that it can ethier a value type or a refrence type
Angius
Angius5mo ago
Yes, there are records and record structs In either case, comparison will be by value
steven preadly
steven preadlyOP5mo ago
hem but if it is a record only then it will be refrence type
Angius
Angius5mo ago
A reference type with value semantics
MODiX
MODiX5mo ago
Angius
REPL Result: Success
record Foo(int Bar);

var a = new Foo(1);
var b = new Foo(1);

a == b
record Foo(int Bar);

var a = new Foo(1);
var b = new Foo(1);

a == b
Result: bool
True
True
Compile: 330.892ms | Execution: 66.034ms | React with ❌ to remove this embed.
MODiX
MODiX5mo ago
Angius
sharplab.io (click here)
var a = new Foo(1);
var b = new Foo(1);
var c = a == b;
record Foo(int Bar);
var a = new Foo(1);
var b = new Foo(1);
var c = a == b;
record Foo(int Bar);
Try the /sharplab command! | React with ❌ to remove this embed.
Angius
Angius5mo ago
Here's what a record compiles down to
steven preadly
steven preadlyOP5mo ago
yes , also i have another question records can be used instead of the class in case i am dealing with databases
Angius
Angius5mo ago
Records, by default, are immutable So if you're doing the fetch-update-save routine with EF, chances are you'd have to explicitly use autoproperties with a setter instead of the default initializer Not sure how's EF's support for with keyword Another option, is using .ExecuteUpdateAsync() instead of fetch-update-save, which will save you a database round trip and work with records
steven preadly
steven preadlyOP5mo ago
this means that once it got created it could not be updated , so i cant be updated with all of records that i want from the database . so it has to be a work around this is from the docs
Not all data models work well with value equality. For example, Entity Framework Core depends on reference equality to ensure that it uses only one instance of an entity type for what is conceptually one entity. For this reason, record types aren't appropriate for use as entity types in Entity Framework Core.
Not all data models work well with value equality. For example, Entity Framework Core depends on reference equality to ensure that it uses only one instance of an entity type for what is conceptually one entity. For this reason, record types aren't appropriate for use as entity types in Entity Framework Core.
mtreit
mtreit5mo ago
To be clear, records are just classes with some stuff implemented automatically and some syntactic sugar to make them more concise to declare (if desired.) But they are still classes at the end of the day.
Angius
Angius5mo ago
Well, records have reference equality as well, so it should be fine
steven preadly
steven preadlyOP5mo ago
i am reading the docs too becuse this is a new concept for me yes i have examined this by myself it works , and also i have examined the value comare
c#
House house = new House();


House house2 = house;


Console.WriteLine(house.Equals(house2));
c#
House house = new House();


House house2 = house;


Console.WriteLine(house.Equals(house2));
Want results from more Discord servers?
Add your server