How to compare 2 List<T> when T implements IEquatable? - c#

I have a class and implements IEquatable:
public class MyObject: IEquatable<MyObject>
{
public string Name { get; set; }
public bool Equals(MyObject other)
{
if (other == null)
return false;
return this.Name.Equals(other.Name);
}
public override bool Equals(object o)
{
if (ReferenceEquals(null, o)) return false;
if (ReferenceEquals(this, o)) return true;
if (o.GetType() != GetType()) return false;
return Equals(o as MyObject);
}
public override int GetHashCode()
{
unchecked
{
int hash = 29;
hash = hash * 31 + Name != null ? Name.GetHashCode() : 0;
return hash;
}
}
}
To keep the example short, I just kept the Name property. The class has other properties though.
Now I have 2 lists (A, B) of MyObject and I want to get a list of items that are in A but missing in B.
How can I do this by using LINQ (preferably) and making sure that IEquatable is used (or Equals) is used?

You can use Enumerable.Except, it will use already your IEquatable<MyObject>:
IEnumerable<MyObject> missingInB = A.Except(B);
Note that the Name property should be readonly if it's used in GetHashCode to identify the object.
LINQ methods will use your overridden Equals and GetHashCode, either by implementing IEquatable<T> or just the inherited from System.Object. Another option: pass a custom IEqualityComparer<T> to Except (or other LINQ methods) if you don't want to modify your class.

Related

Overriding GetHashCode with different properties

I have this object:
public class Foo {
public string MyOwnId { get; set; }
public Guid FooGuid { get; } = Guid.NewGuid();
}
I would like Equals() to only care about those with MyOwnId, otherwise they are never equal. When a Foo has a MyOwnId I try to use it, otherwise I want to use FooGuid.
Since FooGuid probably never will be the same, I did something like this:
public bool Equals(Foo foo) {
if (foo== null) return false;
return MyOwnId.Equals(foo.MyOwnId);
}
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Foo)obj);
}
public override int GetHashCode() {
int hash = 13;
hash = (hash*7) + (!string.IsNullOrEmpty(MyOwnId) ? MyOwnId.GetHashCode() : FooGuid.GetHashCode());
return hash;
}
Is this a proper way to do what I want? Or do I also need change my Equals method so it looks the same like my GetHashCode? For e.g:
public bool Equals(Foo foo) {
if (foo == null) return false;
if (string.IsNullOrEmpty(MyOwnId) || string.IsNullOrEmpty(foo.MyOwnId)) return false;
return MyOwnId.Equals(foo.MyOwnId);
}
Well, let's see. Your implementation of Equals and GetHashCode is erroneous.
Both Equals and GetHashCode must never throw an exception; the counter example is
Foo A = new Foo();
Foo B = new Foo() {
MyOwnId = "bla-bla-bla",
};
// Throws an exception
if (A.Equals(B)) {}
If two instances are equal via Equals these instances must have the same hash code; the counter example is
Foo A = new Foo() {
MyOwnId = "",
};
Foo B = new Foo() {
MyOwnId = "",
};
if (A.Equals(B)) {
// Hashcodes must be equal and they are not
Console.Write(String.Format("{0} != {1}", A.GetHashCode(), B.GetHashCode()));
}
Possible (simplest) implementation
// since you've declared Equals(Foo other) let others know via interface implementation
public class Foo: IEquatable<Foo> {
public string MyOwnId { get; set; }
public Guid FooGuid { get; } = Guid.NewGuid();
public bool Equals(Foo other) {
if (Object.ReferenceEquals(this, other))
return true;
else if (Object.ReferenceEquals(null, other))
return false;
else
return String.Equals(MyOwnId, other.MyOwnId);
}
public override bool Equals(object obj) {
return Equals(obj as Foo); // do not repeat youself: you've got Equals already
}
public override int GetHashCode() {
// String.GetHashCode is good enough, do not re-invent a wheel
return null == MyOwnId ? 0 : MyOwnId.GetHashCode();
}
}
Or do I also need change my Equals method so it looks the same like my GetHashCode?
You change your Equals to match how you want equality to be resolved. You've done this.
You change your GetHashCode() to key on the same information. In this case:
public override int GetHashCode()
{
return MyOwnId == null ? 0 : MyOwnId.GetHashCode();
}
Incidentally, your Equals(object) is a bit overly-complicated. I would use:
public override bool Equals(object obj)
{
return Equals(obj as Foo);
}
This passes handling the case of obj being null to the specific Equals() (which has to handle it too), deals with obj being something that isn't a Foo by passing that Equals() a null (so false anyway) and passes the handling of the case of obj being something derived from Foo to the more specific too (which again, has to handle that).
The short-cut on ReferenceEquals isn't worth doing here as there's only one field being compared, and its comparison will have the same ReferenceEquals shortcut. You don't though handle foo being a derived type in the specialised Foo. If Foo isn't sealed you should include that:
public bool Equals(Foo foo)
{
return (object)foo != null &&
foo.GetType() == GetType() &&
MyOwnId.Equals(foo.MyOwnId);
}
If Foo is sealed then that GetType() comparison should be omitted.
If the logic of the Equals() was more complicated than this then the likes of:
public bool Equals(Foo foo)
{
if ((object)foo == (object)this)
return true;
return (object)foo != null &&
foo.GetType() == GetType() &&
// Some more complicated logic here.
}
Would indeed be beneficial, but again it should be in the specific overload not the general override.
(Doing a reference-equality check is more beneficial again in == overloads, since they have to consider the possibility of both operands being null so they might as well consider that of them both being the same which implicitly includes that case).
A hash function must have the following properties:
If two objects compare as equal, the GetHashCode method for each object must return the same value. However, if two objects do not compare as equal, the GetHashCode methods for the two objects do not have to return different values.
The GetHashCode method for an object must consistently return the same hash code as long as there is no modification to the object state that determines the return value of the object's Equals method. Note that this is true only for the current execution of an application, and that a different hash code can be returned if the application is run again.
For the best performance, a hash function should generate an even distribution for all input, including input that is heavily clustered. An implication is that small modifications to object state should result in large modifications to the resulting hash code for best hash table performance.
Hash functions should be inexpensive to compute.
The GetHashCode method should not throw exceptions.
See https://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.110).aspx

What's the relation between GetHashCode and Equals in a IEqualityComparer implementation? [duplicate]

This question already has answers here:
Why is it important to override GetHashCode when Equals method is overridden?
(15 answers)
IEqualityComparer GetHashCode being called but Equals not
(4 answers)
Closed 8 years ago.
I have a class A that inherits from a class B and implements IEqualityComparer<A>.
This means class A provides its own implementation of both Equals and GetHashCode methods. So far so good.
The problem is that I don't understand why the code behaves in the following way:
debugger will only reach A's Equals implementation breakpoint if A's GetHashCode implementation returns
this.GetHashCode() instead of
obj.GetHashCode(), with "obj" being the parameter that GetHashCode's signature defines(a variable of type A, in my case).
Intuitively, I thought that I should return the hashcode of the object I received, but doing so makes the compiler ignore the instance's Equals implementation.
Why does this happen?
Code demonstration:
public class A : B, IEqualityComparer<A>
{
public bool Equals(A x, A y)
{
//my implementation...
}
public int GetHashCode(A obj)
{
//return obj.GetHashCode(); -> this makes my Equals implementation above be ignored! Why?
return this.GetHashCode(); -> my Equals implementation is used
}
}
It sounds like you are using the wrong interface. IEqualityComparer<> is typically used for a class that compares instances of other types.
Your type should simply implement IEquatable<A> and override Equals(object) and GetHashCode(). Note the signatures.
Like this:
public class A : B, IEquatable<A>
{
public bool Equals(A other)
{
if (other == null || GetType() != other.GetType())
return false;
//your implementation
}
public override bool Equals(object obj)
{
return Equals(obj as A);
}
public override int GetHashCode()
{
//your implementation
}
}
Then you can do stuff like someEnumerableOfA.Distinct() and the Linq method will use your implementation.
The other option is to do:
public class A : B // no interfaces
{
}
public class AEqualComparer : IEqualityComparer<A>
{
public bool Equals(A x, A y)
{
//your implementation
}
public int GetHashCode(A x)
{
//your implementation
}
}
With this other option you need someEnumerableOfA.Distinct(new AEqualComparer ()).
Implementing IEqualityComparer<T> doesn't override the base implementation of GetHashCode and Equals.
Implementing IEqualityComparer<T> allows you to supply an instance of the implementor as an equality comparer for T. This is a common parameter to several linq extensions and generic collection constructors.
Overriding Equals and GetHashCode effects the way instances of a class are tested for equality. Tapping into other implmentations that call Equals and GetHashCode, like the base = and != operators and linq extensions and generic collection constructors where you don't supply an alternative IEqualityComparer<T>.
These concepts are similar but serve different purposes, they are not partially interchangable.
Let me expand with an example,
public class A
{
public string Value1 { get; set; }
public int Value2 { get; set; }
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = (hash * 23) +
StringComparer.Ordinal.GetHashCode(this.Value1);
hash = (hash * 23) + this.Value2;
return hash;
}
}
public override bool Equals(object obj)
{
var a = obj as A;
if (a == null)
{
return false;
}
if (a.Value2 != this.Value2)
{
return false;
}
return StringComparer.Ordinal.Equals(
a.Value1,
this.Value1);
}
}
This implementation of A correctly overrides Equals and GetHashCode, this change is sufficient to ensure that after calling the linq extension
var distinct = aSequneceOfA.Distinct();
distinct will not contain any instances that have both the same Value2 and ordinally comparable Value1. No other interface implementation is necessary to achieve this.
Now, suppose that in some situation I wasn't happy with this ordinal comparison for Value1, perhaps I require some case insensitivity. I might implement an new equality comparer.
public class AComparerInsensitive : IEqualityComparer<A>
{
public bool Equals(A x, A y)
{
if (x == null)
{
return y == null;
}
if (y == null)
{
return false;
}
if (x.Value2 != y.Value2)
{
return false;
}
return StringComparer.CurrentCultureIgnoreCase.Equals(
x.Value1,
y.Value1)
}
public int GetHashCode(A a)
{
if (a == null)
{
return 0;
}
unchecked
{
int hash = 17;
hash = (hash * 23) +
StringComparer.CurrentCultureIgnoreCase.GetHashCode(
a.Value1);
hash = (hash * 23) + a.Value2;
return hash;
}
}
}
This would allow me to call the alternative overload of Distinct,
var insensitivelyDistinct = aSequneceOfA.Distinct(
new AComparerInsensitive());
This overload of distinct ingnores As overridden Equals and GetHashCode and uses AComparerInsensitive to perform the comparison.

Enumerable.Distinct - What methods does your custom class have to implement for it to work?

I've implemented every function that MSDN says is necessary, plus some additional comparison interfaces - nothing seems to work. Following is code (optimized for LinqPad).
The resulting output is all 4 items, not 2 like I expect.
Please don't post work arounds as answers - I want to know how Distinct works
void Main()
{
List<NameClass> results = new List<NameClass>();
results.Add(new NameClass("hello"));
results.Add(new NameClass("hello"));
results.Add(new NameClass("55"));
results.Add(new NameClass("55"));
results.Distinct().Dump();
}
// Define other methods and classes here
public class NameClass : Object
, IEquatable<NameClass>
, IComparer<NameClass>
, IComparable<NameClass>
, IEqualityComparer<NameClass>
, IEqualityComparer
, IComparable
{
public NameClass(string name)
{
Name = name;
}
public string Name { get; private set; }
public int Compare(NameClass x, NameClass y)
{
return String.Compare(x.Name, y.Name);
}
public int CompareTo(NameClass other)
{
return String.Compare(Name, other.Name);
}
public bool Equals(NameClass x, NameClass y)
{
return (0 == Compare(x, y));
}
public bool Equals(NameClass other)
{
return (0 == CompareTo(other));
}
public int GetHashCode(NameClass obj)
{
return obj.Name.GetHashCode();
}
public new int GetHashCode()
{
return Name.GetHashCode();
}
public new bool Equals(object a)
{
var x = a as NameClass;
if (null == x) { return false; }
return Equals(x);
}
public new bool Equals(object a, object b)
{
if (null == a && null == b) { return true; }
if (null == a && null != b) { return false; }
if (null != a && null == b) { return false; }
var x = a as NameClass;
var y = b as NameClass;
if (null == x && null == y) { return true; }
if (null == x && null != y) { return false; }
if (null != x && null == y) { return false; }
return x.Equals(y);
}
public int GetHashCode(object obj)
{
if (null == obj) { return 0; }
var x = obj as NameClass;
if (null != x) { return x.GetHashCode(); }
return obj.GetHashCode();
}
public int CompareTo(object obj)
{
if (obj == null) return 1;
NameClass x = obj as NameClass;
if (x == null)
{
throw new ArgumentException("Object is not a NameClass");
}
return CompareTo(x);
}
}
How Distinct works:
There is at least no implementation of Object.GetHashCode() which is used for initial comparison of objects: basic version of Distinct compares (actually puts in dictionary) by Object.GetHashCode first, than if hash code matches by Object.Equals.
To be precise Enumerable.Distinct(this IEnumerable source) uses EqualityComparer<NameClass>.Default to finally check for equality (note that if hash codes don't match it will not reach that portion of the comparison which is why your sample does not work).
The default equality comparer, Default, is used to compare values of the types that implement the IEquatable generic interface.
EqualityComparer.Default in turn actually allows to use class without IEquatable<T> at all falling back directly to Object.Equals:
The Default property checks whether type T implements the System.IEquatable interface and, if so, returns an EqualityComparer that uses that implementation. Otherwise, it returns an EqualityComparer that uses the overrides of Object.Equals and Object.GetHashCode provided by T.
So for basic Distinct to work you just need correct version of Equals/GetHashCode. IEquatable is optional, but must match behavior of GetHashCode in the class.
How to fix:
Your sample have public new int GetHashCode() method, which likely should be public override int GetHashCode() (Same for Equals).
Note that public new int... does not mean "override", but instead "create new version of the method that hides old one". It does not impact callers that call method via pointer to parent object.
Personally I think new should rarely be used in defining methods. Some suggestions when it is useful are covered in Usecases for method hiding using new.
You don't have to implement any interface, just GetHashCode and Equals methods correctly:
public class NameClass
{
public NameClass(string name)
{
Name = name;
}
public string Name { get; private set; }
public override bool Equals(object obj)
{
var other = obj as NameClass;
return other != null && other.Name == this.Name;
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
}
Enumerable.Distinct<TSource> Method:
It uses the default equality comparer, Default, to compare values.
EqualityComparer.Default:
The Default property checks whether type T implements the System.IEquatable<T> interface and, if so, returns an EqualityComparer<T> that uses that implementation. Otherwise, it returns an EqualityComparer<T> that uses the overrides of Object.Equals and Object.GetHashCode provided by T.
IEquatable<T> Interface:
If you implement IEquatable<T>, you should also override the base class implementations of Object.Equals(Object) and GetHashCode so that their behavior is consistent with that of the IEquatable<T>.Equals method.
Overriding methods:
The override modifier is required to extend or modify the abstract or virtual implementation of an inherited method, property, indexer, or event.
So your code should look like this:
public class NameClass : IEquatable<NameClass>
{
public NameClass(string name)
{
Name = name;
}
public string Name { get; private set; }
// implement IEquatable<NameClass>
public bool Equals(NameClass other)
{
return (other != null) && (Name == other.Name);
}
// override Object.Equals(Object)
public override bool Equals(object obj)
{
return Equals(obj as NameClass);
}
// override Object.GetHashCode()
public override GetHashCode()
{
return Name.GetHashCode();
}
}
So, first off, Distinct will, as per it's documentation, use EqualityComparer<T>.Default to compare objects if no custom equality comparer is provided (you provided none).
EqualityComparer<T>.Default, as per its documentation, will look to see if the object implements IEquatable<T>, if it does it will use that implementation of Equals.
Regardless of whether or not the type implements IEquatable<T>, EqualityComparer<T>.Default will use the object.GetHashCode method to get the has code of the object. IEquatable<T>, unfortunately, does not force you to also override the object's GetHashCode implementation, and in your case, while you do implement IEquatable<T>, your code does not override the object's GetHashCode implementation.
As a result of this Distinct is actually using the proper Equals method for your type, but it's using the wrong GetHashCode method. Whenever you're hashing objects and that type has an Equals and GetHashCode implementation that's out of sync problems ensue. What's happening is that in whatever hash based collection it's sending the two "equal" objects to different buckets, so they never even get to the point where their Equals methods are called on each other. If you happened to get lucky and there was a hash collection and the objects were coincidentally sent to the same bucket, then, since the Equals method is what you intended it would actually work, but the odds of that happening are...very low. (In this specific case, about 2/2147483647, or
9.3e-10.
While you do provide a new GetHashCode method in NameClass, it is hiding the object implementation, not overriding it. If you change your GetHashCode implementation to use override rather than new then your code will work.
I just realized I messed up my sample code - my class derives from DependencyObject, not Object. I can't override thew GetHashCode or Equals functions because the DependencyObject class is sealed.

ExceptWith in HashSet for complex types

I have HashSet of my custom class:
public class Vertex
{
public string Name;
public override bool Equals(object obj)
{
var vert = obj as Vertex;
if (vert !=null)
{
return Name.Equals(vert.Name, StringComparison.InvariantCulture);
}
return false;
}
}
And now I have tow hashsets
HashSet<Vertex> hashSet1 = new HashSet<Vertex>();
HashSet<Vertex> hashSet1 = new HashSet<Vertex>();
And now I'd like to have in hashSet1 only Vertexes that are not in hashSet2
So I use ExceptWith method
hashSet1.ExceptWith(hashSet2);
But this doesn't work.
I suppose that this doesn't work because I have complex type.
So the question is: is there some interface required to be implemented in Vertex class to make this thing work?
I know that while creation of HashSet I can pass a EqualityComparer but it seems to me that it would be more elegant to implement some comparing interface method in Vertex class.
Is it possible or I just doesn't understand sth?
Thanks.
When overriding Equals you should also override GetHashCode. HashSet (and other hashing structures like Dictionary) will first calculate a hash code for your objects to locate them in tne structure before comparing elements with Equals.
public override int GetHashCode()
{
return StringComparer.InvariantCulture.GetHashCode(this.Name);
}
You don't have to implement any interface (although IEquatable<T>) is encouraged. When you create a hash-set without specifying an equality-comparer, it defaults to using EqualityComparer<T>.Default, which asks the objects themselves to compare themselves to each other (special-casing null references).
However, in your case, your equality contract is broken since you haven't overriden GetHashCode. Here's how I would fix your type:
public class Vertex : IEquatable<Vertex>
{
public string Name { get; private set; }
public Vertex(string name)
{
Name = name;
}
public override int GetHashCode()
{
return StringComparer.InvariantCulture.GetHashCode(Name);
}
public override bool Equals(object obj)
{
return Equals(obj as Vertex);
}
public bool Equals(Vertex obj)
{
return obj != null && StringComparer.InvariantCulture.Equals(Name, obj.Name);
}
}
Would you mind overriding the .GetHashCode()too?
Here's the reference.
You have to override GetHashCode with Equals overriding.
Object.Equals Method:
Types that override Equals(Object) must also override GetHashCode; otherwise, hash tables might not work correctly.

c# List<T>.Contains() Method Returns False

In the code block below I would expect dictCars to contain:
{ Chevy:Camaro, Dodge:Charger }
But, dictCars comes back empty. Because this line returns false each time it's called:
if(myCars.Contains(new Car(Convert.ToInt64(strCar.Split(':')[1]),strCar.Split(':')[2])))
Code block:
public class Car
{
public long CarID { get; set; }
public string CarName { get; set; }
public Car(long CarID, string CarName)
{
this.CarID = CarID;
this.CarName = CarName;
}
}
List<Car> myCars = new List<Car>();
myCars.Add(new Car(0,"Pinto"));
myCars.Add(new Car(2,"Camaro"));
myCars.Add(new Car(3,"Charger"));
Dictionary<string, string> dictCars = new Dictionary<string, string>();
string strCars = "Ford:1:Mustang,Chevy:2:Camaro,Dodge:3:Charger";
String[] arrCars = strCars.Split(',');
foreach (string strCar in arrCars)
{
if(myCars.Contains(new Car(Convert.ToInt64(strCar.Split(':')[1]),strCar.Split(':')[2])))
{
if (!dictCars.ContainsKey(strCar.Split(':')[0]))
{
dictCars.Add(strCar.Split(':')[0], strCar.Split(':')[2]);
}
}
}
return dictCars;
Question: What am I doing wrong with my List.Contains implementation?
Thanks in advance!
You need to tell Contains what makes two Cars equal. By default it will use ReferenceEquals which will only call two objects equal if they are the same instance.
Either override Equals and GetHashCode in your Car class or define an IEqualityComparer<Car> class and pass that to Contains.
If two Cars that have the same CarID are "equal" then the implementation is pretty straightforward:
public override bool Equals(object o)
{
if(o.GetType() != typeof(Car))
return false;
return (this.CarID == ((Car)o).CarID);
}
public override int GetHashCode()
{
return CarID.GetHashCode();
}
Your Car class is a reference type. By default reference types are compared to each other by reference, meaning they are considered the same if they reference the same instance in memory. In your case you want them to be considered equal if they contain the same values.
To change the equality behavior, you need to override Equals and GetHashCode.
If two cars are equal only when ID and Name are equal, the following is one possible implementation of the equality members:
protected bool Equals(Car other)
{
return CarID == other.CarID && string.Equals(CarName, other.CarName);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
var other = obj as Car;
return other != null && Equals(other);
}
public override int GetHashCode()
{
unchecked
{
return (CarID.GetHashCode() * 397) ^
(CarName != null ? CarName.GetHashCode() : 0);
}
}
This implementation has been created automatically by ReSharper.
It takes into account null values and the possibility of sub-classes of Car. Additionally, it provides a useful implementation of GetHashCode.
You can add this code, by implementing IEquatable
public class Car: IEquatable<Car>
{
......
public bool Equals( Car other )
{
return this.CarID == other.CarID && this.CarName == other.CarName;
}
}
Link : http://msdn.microsoft.com/fr-fr/library/vstudio/ms131187.aspx
You are assuming that two Car instances that have the same CarID and CarName are equal.
This is incorrect. By default, each new Car(...) is different from each other car, since they are references to different objects.
There are a few ways to "fix" that:
Use a struct instead of a class for your Car.
Structs inherit ValueType's default implementation of Equals, which compares all fields and properties to determine equality.
Note that in this case, it is recommended that you make your Car struct immutable to avoid common problems with mutable structs.
Override Equals and GetHashCode.
That way, List.Contains will know that you intend Cars with the same ID and Name to be equal.
Use another method instead of List.Contains.
For example, Enumerable.Any allows you to specify a predicate that can be matched:
bool exists = myCars.Any(car => car.ID == Convert.ToInt64(strCar.Split(':')[1])
&& car.Name = strCar.Split(':')[2]);
You need to implement Equals. Most probably as:
public override bool Equals(object obj)
{
Car car = obj as Car;
if(car == null) return false;
return car.CarID == this.CarID && car.CarName == this.CarName;
}
Your car class needs to implement interface IEquatable and define an Equals method, otherwise the contains method is comparing the underlying references.
You need to implement the IEqualityComparer
More information on how to do it can be found here;
http://msdn.microsoft.com/en-us/library/bb339118.aspx
// Custom comparer for the class
class CarComparer : IEqualityComparer<Car>
{
// Products are equal if their names and product numbers are equal.
public bool Equals(Car x, Car y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the properties are equal.
return x.CarID == y.CarID && x.CarName == y.CarName;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Car car)
{
//Check whether the object is null
if (Object.ReferenceEquals(car, null)) return 0;
//Get hash code for the Name field if it is not null.
string hashCarName = car.CarName == null ? 0 : car.CarName.GetHashCode();
//Get hash code for the ID field.
int hashCarID = car.CarID.GetHashCode();
//Calculate the hash code for the product.
return hashCarName ^ hashCarID;
}
Check for equality;
CarComparer carComp = new CarComparer();
bool blnIsEqual = CarList1.Contains(CarList2, carComp);
A collection can never "contain" a newly newed object which uses the default Object.Equals comparison. (The default comparison is ReferenceEquals, which simply compares instances. This will never be true comparing an existing Car with a new Car())
To use Contains in this way, you will need to either:
Override Car.Equals (and Car.GetHashCode) to specify what it means to be equivalent, or
Implement an IEqualityComparer<Car> to compare the instances and specify that in your call to Contains.
Note the side effect that in the first option, other uses of Car.Equals(Car) will also use this comparison.
Otherwise, you can use Any and specify the comparison yourself (but IMHO this smells a little funny - a Car should know how to compare itself):
if(myCars.Any(c=> c.CarID == Convert.ToInt64(strCar.Split(':')[1]) && c.CarName == strCar.Split(':')[2]))
myCars.Contains(newCar)
myCars.Where(c => c.CarID == newCar.CarID && c.CarName==newCar.CarName).Count() > 0

Categories

Resources