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
mtreit2mo 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 preadly2mo ago
i did not get this can you explain
mtreit
mtreit2mo ago
public record Customer(int Id, string Name);
mtreit
mtreit2mo 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
mtreit2mo ago
Yes, that's the way to fix it.
steven preadly
steven preadly2mo ago
record is a type that are different than class
Angius
Angius2mo 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 preadly2mo 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
Angius2mo ago
Yes, there are records and record structs In either case, comparison will be by value
steven preadly
steven preadly2mo ago
hem but if it is a record only then it will be refrence type
Angius
Angius2mo ago
A reference type with value semantics
MODiX
MODiX2mo 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
MODiX2mo 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
Angius2mo ago
Here's what a record compiles down to
steven preadly
steven preadly2mo ago
yes , also i have another question records can be used instead of the class in case i am dealing with databases
Want results from more Discord servers?
Add your server