Given the class as follows,
public class Number
{
public int X { get; set; }
public int Y { get; set; }
}
How to define an overload operator == so that I can use the following statement:
Number n1 = new Number { X = 10, Y = 10 };
Number n2 = new Number { X = 100, Y = 100 };
if (n1 == n2)
Console.WriteLine("equal");
else
Console.WriteLine("not-equal");
// Updated based on comments as follows //
Here is a further question:
It seems to me that C# does operator overload differently from that of C++.
In C++, this overloaded operator is defined outside of the targeting class as a standalone function. Here in C#, this overload function in fact is embedded into the targeting class.
Can someone give me some comments on this topic?
Thank you
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
public class Number
{
public int X { get; set; }
public int Y { get; set; }
public Number() { }
public Number(int x, int y)
{
X = x;
Y = y;
}
public static bool operator==(Number a, Number b)
{
return ((a.X == b.X) && (a.Y == b.Y));
}
public static bool operator !=(Number a, Number b)
{
return !(a == b);
}
public override string ToString()
{
return string.Format("X: {0}; Y: {1}", X, Y);
}
public override bool Equals(object obj)
{
var objectToCompare = obj as Number;
if ( objectToCompare == null )
return false;
return this.ToString() == obj.ToString();
}
public override int GetHashCode()
{
return this.ToString().GetHashCode();
}
}
class Program
{
static void Main(string[] arg)
{
Number n1 = new Number { X = 10, Y = 10 };
Number n2 = new Number { X = 10, Y = 10 };
if (n1 == n2)
Console.WriteLine("equal");
else
Console.WriteLine("not-equal");
Console.ReadLine();
}
}
}
public static bool operator ==(YourClassType a, YourClassType b)
{
// do the comparison
}
More information here. In short:
Any type that overloads operator == should also overload operator !=
Any type that overloads operator == should also should override Equals
It is recommended that any class that overrides Equals also override GetHashCode
From the MSDN Docs:
public static bool operator ==(ThreeDPoint a, ThreeDPoint b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
{
return false;
}
// Return true if the fields match:
return a.x == b.x && a.y == b.y && a.z == b.z;
}
public static bool operator !=(ThreeDPoint a, ThreeDPoint b)
{
return !(a == b);
}
Here is a short example of how to do it, but I very strongly recommend reading Guidelines for Overloading Equals() and Operator == (C# Programming Guide) to understand the interaction between Equals() and == and so on.
public class Number
{
public int X { get; set; }
public int Y { get; set; }
public static bool operator ==(Number a, Number b)
{
// TODO
}
}
overload the operator yourself:
public static bool operator ==(Number a, Number b)
{
// do stuff
return true/false;
}
Related
There is a class of Products:
public class ProductWithFeatures
{
public string Name { get; set; }
public ICollection<Feature> Features { get; set; }
}
public class Feature
{
public int Id { get; set; }
public Feature(int Id)
{
this.Id = Id;
}
}
I want to write an IEqualityComparer for this (i already have one for Feature).
The one for Feature is like this:
public class FeatureComparer : IEqualityComparer<Feature>
{
public bool Equals(Feature x, Feature y)
{
return x.Id == y.Id;
}
public int GetHashCode(Feature obj)
{
return obj.Id;
}
}
And what i wrote so far on the other one is this:
public class ProductComparer : IEqualityComparer<LinqHomework.ProductWithFeatures>
{
public bool Equals(ProductWithFeatures x, ProductWithFeatures y)
{
return x.Name == y.Name && LinqHomework.FeatureComparer.Equals(x.Features, y.Features);
}
public int GetHashCode(ProductWithFeatures obj)
{
}
}
I can't find an answer anywhere about this. Does anybody know how to write it?
Two ProductWithFeaturess are equal if they have the same name, and have the same features in the same order.
public class ProductComparer : IEqualityComparer<LinqHomework.ProductWithFeatures>
{
public bool Equals(ProductWithFeatures x, ProductWithFeatures y)
{
return x.Name == y.Name && x.Features.SequenceEqual(y.Features, new LinqHomework.FeatureComparer());
}
public int GetHashCode(ProductWithFeatures obj)
{
int hash = obj.Name.GetHashCode();
var featureComparer = new LinqHomework.FeatureComparer();
foreach (var feature in obj.Features)
{
hash = hash * 23 + featureComparer.GetHashCode(feature);
}
return hash;
}
}
This is a simple approach, which can be improved in a number of ways.
First, let's give our FeatureComparer a Default property, so we don't need to keep creating new instances:
public class FeatureComparer : IEqualityComparer<Feature>
{
public static FeatureComparer Default { get; } = new FeatureComparer();
// ... as before
}
This lets us write:
public class ProductComparer : IEqualityComparer<LinqHomework.ProductWithFeatures>
{
public bool Equals(ProductWithFeatures x, ProductWithFeatures y)
{
return x.Name == y.Name && x.Features.SequenceEqual(y.Features, LinqHomework.FeatureComparer.Default);
}
public int GetHashCode(ProductWithFeatures obj)
{
int hash = obj.Name.GetHashCode();
foreach (var feature in obj.Features)
{
hash = hash * 23 + LinqHomework.FeatureComparer.Default.GetHashCode(feature);
}
return hash;
}
}
We're also not handling the case where our methods are passed null, or the name of a feature is null, so let's deal with those. We can also test whether x and y are the same object in Equals.
We'll also do the integer operations in an unchecked block in case it overflows (and the assembly is compiled with /checked).
Note that we use ReferenceEquals instead of ==, in case you end up implementing the == operator in your types.
public class ProductComparer : IEqualityComparer<LinqHomework.ProductWithFeatures>
{
public bool Equals(ProductWithFeatures x, ProductWithFeatures y)
{
if (ReferenceEquals(x, y))
return true;
if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
return false;
if (x.Name != y.Name)
return false;
if (ReferenceEquals(x.Features, y.Features))
return true;
if (ReferenceEquals(x.Features, null) || ReferenceEquals(y.Features, null))
return false;
if (!x.Features.SequenceEquals(y.Features, LinqHomework.FeatureComparer.Default))
return false;
return true;
}
public int GetHashCode(ProductWithFeatures obj)
{
if (ReferenceEquals(obj, null))
return 0;
unchecked
{
int hash = obj.Name?.GetHashCode() ?? 0;
if (!ReferenceEquals(obj.Features, null))
{
foreach (var feature in obj.Features)
{
hash = hash * 23 + LinqHomework.FeatureComparer.Default.GetHashCode(feature);
}
return hash;
}
}
}
}
It's really up to you. I personally would go for something like
public int GetHashCode( ProductWithFeatures obj )
{
string toHash = obj.Name;
foreach( var feature in obj.Features )
toHash += feature.GetHashCode();
return toHash.GetHashCode();
}
It's not the nicest code ever, but it does what it's supposed to do.
I'm running into a problem where the contains method is return false even though it exist in the list. Can someone tell me what's wrong with this?
Program.CS
points.Add(new Point(-4, -7));
points.Add(new Point(0, 0));
points.Add(new Point(1, 2));
points.Add(new Point(-4, 5));
points.Insert(2, new Point(3, 1));
points.Add(new Point(7, -2));
points[0] = new Point(2, 1);
points.RemoveAt(2);
bool returnPoint = false;
returnPoint = points.Contains(new Point(1, 2));
PointList.CS
public bool Contains(Point item)
{
return _Points.Contains(item);
}
Point.CS
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
X = x;
Y = y;
}
Since Point is a class, it is a reference type. By default, reference types check for referential equality. If you want to get the behavior you're expecting, you should override the Equals and GetHashCode methods in Point, and it probably wouldn't hurt to implement IEquatable<Point> while you're at it, along with the == and != operators.
An example implementation would look like this:
public class Point : IEquatable<Point>
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
X = x;
Y = y;
}
public bool Equals(Point other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return X == other.X && Y == other.Y;
}
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((Point)obj);
}
public override int GetHashCode()
{
unchecked
{
return (X * 397) ^ Y;
}
}
public static bool operator ==(Point left, Point right)
{
return Equals(left, right);
}
public static bool operator !=(Point left, Point right)
{
return !Equals(left, right);
}
}
If that seems like a lot, well, it is. Unfortunately, implementing equality tends to require a good amount of boiler plate in C#. If we get Record types in C# 8 some of the pain may be alleviated, but until then this is the typical approach.
Point is a reference type, so you're unintentionally comparing references, not properties.
You can compare properties by using LINQ's Any() and passing a lambda expression that performs the comparison you wish.
//using System.Linq;
returnPoint = points.Any( p => p.X == 1 && p.Y == 2 );
Contains in ArrayList uses implementation of Equals() on the objects. Currently you are checking if object references are equal.
Point point = new Point(5, 2);
Point refPoint = point; // refer to same object
points.Add(point);
bool returnPoint = false;
returnPoint = points.Contains(refPoint); // return true
Need to override Equals() and GetHashcode in your class for reference types:
public override bool Equals(object other) {
Point otherPoint = other as Point;
if(otherPoint != null)
return (X.Equals(otherPoint.X) && (Y.Equals(otherPoint.Y)));
return false;
}
you need valueObject for best practice solution and For comparison only x and y may not. you should think of functional processes as DDD design
look here
public abstract class ValueObject
{
protected static bool EqualOperator(ValueObject left, ValueObject right)
{
if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null))
{
return false;
}
return ReferenceEquals(left, null) || left.Equals(right);
}
protected static bool NotEqualOperator(ValueObject left, ValueObject right)
{
return !(EqualOperator(left, right));
}
protected abstract IEnumerable<object> GetAtomicValues();
public override bool Equals(object obj)
{
if (obj == null || obj.GetType() != GetType())
{
return false;
}
var other = (ValueObject)obj;
var thisValues = GetAtomicValues().GetEnumerator();
var otherValues = other.GetAtomicValues().GetEnumerator();
while (thisValues.MoveNext() && otherValues.MoveNext())
{
if (ReferenceEquals(thisValues.Current, null) ^ ReferenceEquals(otherValues.Current, null))
{
return false;
}
if (thisValues.Current != null && !thisValues.Current.Equals(otherValues.Current))
{
return false;
}
}
return !thisValues.MoveNext() && !otherValues.MoveNext();
}
public override int GetHashCode()
{
return GetAtomicValues()
.Select(x => x != null ? x.GetHashCode() : 0)
.Aggregate((x, y) => x ^ y);
}
}
your PointList.cs
public class PointList
{
public string Bla { get; set; }
public List<Point> Points { get; protected set; } = new List<Point>();
public void AddPoint(int x, int y)
{
AddPoint(new Point(x, y));
}
public void AddPoint(Point p)
{
if (!Points.Any(x => x.Equals(p)))
Points.Add(p);
}
public void RemovePoint(int x, int y)
{
RemovePoint(new Point(x, y));
}
public void RemovePoint(Point point)
{
Points.Remove(point);
}
public Point GetPoint(int x, int y)
{
return GetPoint(new Point(x, y));
}
public Point GetPoint(Point point)
{
return Points.FirstOrDefault(x => x.Equals(point));
}
}
your Point.cs
public class Point : ValueObject
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
X = x;
Y = y;
}
protected override IEnumerable<object> GetAtomicValues()
{
yield return X;
yield return Y;
}
}
Examples
class Program
{
static void Main(string[] args)
{
var list = new PointList();
list.AddPoint(1, 1);
list.AddPoint(1, 2);
list.AddPoint(14, 53);
list.RemovePoint(1, 1);
list.RemovePoint(new Point(1, 2));
var p2 = list.GetPoint(14, 53);
var p1 = list.GetPoint(new Point(14, 53));
}
}
Similar questions have been asked, but I'm not sure I understand the answers correctly. I am referring to a situation where the equality operator is overridden in one or both classes. Please explain if I'm right. If I write if(a == b) { ... }, then equality operator of the class of "a" is used and in case of if(b == a) { ... } is used then equality operator defined in the class of "b". The equality operator of which class is used if I write if(null == a) { ... }.
situation where the equality operator is overridden in one or both classes
We can do that and test... something like the following?
class A
{
public static bool operator == (A a, B b)
{
Console.WriteLine("A");
return false;
}
public static bool operator != (A a, B b)
{
Console.WriteLine("A");
return false;
}
public static bool operator == (B b, A a)
{
Console.WriteLine("A");
return false;
}
public static bool operator != (B b, A a)
{
Console.WriteLine("A");
return false;
}
public override bool Equals(object o)
{
return false;
}
public override int GetHashCode()
{
return 0;
}
}
class B
{
public static bool operator == (A a, B b)
{
Console.WriteLine("B");
return false;
}
public static bool operator != (A a, B b)
{
Console.WriteLine("B");
return false;
}
public static bool operator == (B b, A a)
{
Console.WriteLine("B");
return false;
}
public static bool operator != (B b, A a)
{
Console.WriteLine("B");
return false;
}
public override bool Equals(object o)
{
return false;
}
public override int GetHashCode()
{
return 0;
}
}
Then you write code such as:
A a = new A();
B b = new B();
if (a == b)
{
// ...
}
Then you get:
CS0034 Operator '==' is ambiguous on operands of type 'A' and 'B'
Does that answer your question? Have a look at the code, when you define the operator == you specify the types of the parameters, and the compiler uses that to choose the operator to call. In this case it finds two operators that have operands A and B in that order and that results in an ambiguous call (the compiler does not know - does not have a way to decide - which one to use).
If I write if(a == b) { ... }, then equality operator of the class of "a" is used and in case of if(b == a) { ... } is used then equality operator defined in the class of "b"
That depends on the types of the operands. If you always put the operant of the type of the current class as first, then that is true. For example:
void Main()
{
A a = new A();
B b = new B();
if (a == b)
{
// ...
}
}
class A
{
public static bool operator == (A a, B b)
{
Console.WriteLine("A");
return false;
}
public static bool operator != (A a, B b)
{
Console.WriteLine("A");
return false;
}
public override bool Equals(object o)
{
return false;
}
public override int GetHashCode()
{
return 0;
}
}
class B
{
public static bool operator == (B b, A a)
{
Console.WriteLine("B");
return false;
}
public static bool operator != (B b, A a)
{
Console.WriteLine("B");
return false;
}
public override bool Equals(object o)
{
return false;
}
public override int GetHashCode()
{
return 0;
}
}
Output: A.
However, if define the operators with the operands in the opposite order...
void Main()
{
A a = new A();
B b = new B();
if (a == b)
{
// ...
}
}
class A
{
public static bool operator == (B b, A a)
{
Console.WriteLine("A");
return false;
}
public static bool operator != (B b, A a)
{
Console.WriteLine("A");
return false;
}
public override bool Equals(object o)
{
return false;
}
public override int GetHashCode()
{
return 0;
}
}
class B
{
public static bool operator == (A a, B b)
{
Console.WriteLine("B");
return false;
}
public static bool operator != (A a, B b)
{
Console.WriteLine("B");
return false;
}
public override bool Equals(object o)
{
return false;
}
public override int GetHashCode()
{
return 0;
}
}
Output: B.
The equality operator of which class is used if I write if(null == a) { ... }
First, let us be clear. B or any other classes are irrelevant here. They do not affect the outcome of this comparison, because you are not using them here. It would be very inconvenient if they did.
Let us try:
void Main()
{
A a = new A();
if (null == a)
{
// ...
}
}
class A
{
public static bool operator == (A a, B b)
{
Console.WriteLine("A");
return false;
}
public static bool operator != (A a, B b)
{
Console.WriteLine("A");
return false;
}
public override bool Equals(object o)
{
return false;
}
public override int GetHashCode()
{
return 0;
}
}
class B
{
public static bool operator == (B b, A a)
{
Console.WriteLine("B");
return false;
}
public static bool operator != (B b, A a)
{
Console.WriteLine("B");
return false;
}
public override bool Equals(object o)
{
return false;
}
public override int GetHashCode()
{
return 0;
}
}
Output: .
We get no output, because the called operator is none of the ones defined here... intead it is using the default operator (the one for object).
Wait! What if I change the order of operands?
void Main()
{
A a = new A();
if (null == a)
{
// ...
}
}
class A
{
public static bool operator == (B b, A a)
{
Console.WriteLine("A");
return false;
}
public static bool operator != (B b, A a)
{
Console.WriteLine("A");
return false;
}
public override bool Equals(object o)
{
return false;
}
public override int GetHashCode()
{
return 0;
}
}
class B
{
public static bool operator == (A a, B b)
{
Console.WriteLine("B");
return false;
}
public static bool operator != (A a, B b)
{
Console.WriteLine("B");
return false;
}
public override bool Equals(object o)
{
return false;
}
public override int GetHashCode()
{
return 0;
}
}
Output: A.
Now we are using the operator on A because it matches the operand types better than the default operator does.
Simply try it out.
public class Program
{
public static void Main()
{
var foo = new Foo();
if(foo == null)
{
}
if(null == foo)
{
}
}
}
public class Foo
{
public static bool operator ==(Foo a, Foo b)
{
Console.WriteLine("Foo operator == called");
return ReferenceEquals(a, b);
}
public static bool operator !=(Foo a, Foo b)
{
Console.WriteLine("Foo operator != called");
return !(a == b);
}
public override bool Equals(object obj)
{
Console.WriteLine("Foo Equals() called");
return ReferenceEquals(this, obj);
}
public override int GetHashCode()
{
Console.WriteLine("Foo GetHashCode() called");
return base.GetHashCode();
}
}
Output:
Foo operator == called
Foo operator == called
So in both cases the equality operator of class Foo will be called.
I created two classes almost identical. Both represent a Pair (x,y) but in one of them I overrode the GetHashCode and Equals methods. I was told that when the HashCode is different the Collections takes them as different elements and does not even bother to actually compare them with the equals. However, it turns out that I implemented an EqualityComparer for the class that do not override the GetHashCode and Equals and everything works fine even when the HashCodes are still different.
Take a look at my Console Project:
using System;
using System.Collections.Generic;
using System.Linq;
namespace matrixExample
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Same Hash but no insertion: as expected");
HashSet<MyPair> hash = new HashSet<MyPair>();
MyPair one = new MyPair { X = 10, Y = 2 };
MyPair copyOfOne = new MyPair { X = 10, Y = 2 };
Console.WriteLine(one.GetHashCode() + " " + hash.Add(one));
Console.WriteLine(copyOfOne.GetHashCode() + " " + hash.Add(copyOfOne));
Console.WriteLine("-----------------------------------------");
Console.WriteLine("Different Hash but no insertion! why?");
HashSet<MyPairWithoutOverride> hash2 = new HashSet<MyPairWithoutOverride>(new SameHash());
MyPairWithoutOverride a1 = new MyPairWithoutOverride { X = 10, Y = 2 };
MyPairWithoutOverride a1copy = new MyPairWithoutOverride { X = 10, Y = 2 };
Console.WriteLine(a1.GetHashCode() + " " + hash2.Add(a1));
Console.WriteLine(a1copy.GetHashCode() + " " + hash2.Add(a1copy));
}
public class MyPair
{
public int X { get; set; }
public int Y { get; set; }
public override int GetHashCode()
{
return X * 10000 + Y;
}
public override bool Equals(object obj)
{
MyPair other = obj as MyPair;
return X == other.X && Y == other.Y;
}
}
public class MyPairWithoutOverride
{
public int X { get; set; }
public int Y { get; set; }
}
public class SameHash : EqualityComparer<MyPairWithoutOverride>
{
public override bool Equals(MyPairWithoutOverride p1, MyPairWithoutOverride p2)
{
return p1.X == p2.X && p1.Y == p2.Y;
}
public override int GetHashCode(MyPairWithoutOverride i)
{
return base.GetHashCode();
}
}
}
}
Your problem is here
public override int GetHashCode(MyPairWithoutOverride i)
{
return base.GetHashCode();
}
You're returning base.GetHashCode() which is actually the hash code of the SameHash class. So you actually are returning the same hash code every single time.
If you return i.GetHashCode() then it will behave as expected.
I have a class that I use to describe a XYZ coordinate along with 3 properties.
The class looks like this:
class dwePoint
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public string Prop3 { get; set; }
public override bool Equals(object obj)
{
return Equals(obj as dwePoint);
}
protected bool Equals(dwePoint other)
{ //This doesnt seem to work
if(Prop1== "Keep")
{
return false;
}
return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = X.GetHashCode();
hashCode = (hashCode * 397) ^ Y.GetHashCode();
hashCode = (hashCode * 397) ^ Prop1.GetHashCode();
hashCode = (hashCode * 397) ^ Z.GetHashCode();
return hashCode;
}
}
}
Checking the XYZ on the Equals, I can filter out duplicates only based on the actual coordinates, ignoring the properties.
In my code, I use a list, so I call the List.Distinct()
Now there is one thing I cant figure out yet:
It is possible there are 2 points with the same XYZ, but with different properties.
In that case I always want to keep the one with a specific string (for example "Keep") and always remove the one that has some other value.
I was already trying some if statements, without any luck...
How should I handle this ?
What you want is not really possible with Distinct since it uses your Equals as it's only input for equality (as it should), so it has no way to even be aware that there could be a difference between the objects.
I think it would be a better design for you to compose your class using a new class, e.g. Point3D containing your coordinates and your 3 properties. Then you can group by the point, and for everything that has more than one equal point, apply your own logic as to which to keep.
In code:
class Point3D
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
// Equals and get hash code here
}
class dwePoint
{
Point3D Coordinate {get;}
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public string Prop3 { get; set; }
}
// Filter list by applying grouping and your custom logic
points = points.GroupBy(p => p.Coordinate)
.Select(x =>
x.OrderByDescending(p => p.Prop1 == "Keep") // Sort so the element you want to keep is first
.First() // If there is only one element, the ordering will not matter
).ToList();
If you really want, the GroupBy also works with your current class design, since only the coordinates takes part in the Equals.
Your GetHashCode runs into a nullref if Prop1 == null, you should fix that.
And another solution: use Aggregate and Lamda to distinct your list. The Equal() on your class only compares the X,Y and Z - the Aggregate lambda makes sure you keep what you want. Probably put the Aggregate in a extension method or Function.
static void Main()
{
List<dwePoint> points = new List<dwePoint>();
// Testdata
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++)
for (int z = 0; z < 3; z++)
{
points.Add(new dwePoint { X = x, Y = y, Z = z });
if (x == y && x == z) // and some duplicates to Keep
points.Add(new dwePoint { X = x, Y = y, Z = z, Prop1 = "Keep" });
}
// prefer the ones with "Keep" in Prop1
var distincts = points.Aggregate(new HashSet<dwePoint>(), (acc, p) =>
{
if (acc.Contains(p))
{
var oldP = acc.First(point => point.X == p.X && point.Y == p.Y && point.Z == p.Z);
if (oldP.Prop1 == "Keep")
{
// do nothing - error, second point with "keep"
}
else
{
acc.Remove(oldP);
acc.Add(p); // to use this ones other props later on ....
}
}
else
acc.Add(p);
return acc;
}).ToList();
Console.WriteLine(string.Join(" - ", points));
Console.WriteLine(string.Join(" - ", distincts));
Console.ReadLine();
}
private class dwePoint
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public string Prop3 { get; set; }
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public override bool Equals(object obj)
{
return Equals(obj as dwePoint);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = X.GetHashCode();
hashCode = (hashCode * 397) ^ Y.GetHashCode();
hashCode = (hashCode * 397) ^ Z.GetHashCode();
return hashCode;
}
}
public override string ToString() => $"{X}-{Y}-{Z}-{Prop1}-{Prop2}-{Prop3}";
protected bool Equals(dwePoint other)
{
return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);
}
}
I had the same answer in mind as driis provided..
But, I would like to provide you with another option.
You can write a Distinct on your own as an extension method.
Here is a work around. I wrote a sample code, so that you can understand better.
static class Program
{
static void Main(string[] args)
{
List<Abc> list = new List<Abc>()
{
new Abc()
{
a = 5,
b = 6,
s = "Phew"
},
new Abc()
{
a = 9,
b = 10,
s = "Phew"
},
new Abc()
{
a = 5,
b = 6,
s = "Keep"
},
new Abc()
{
a = 9,
b = 10,
s = "Keep"
},
new Abc()
{
a = 5,
b = 6,
s = "Phew"
},
new Abc()
{
a = 9,
b = 10,
s = "Phew"
},
};
list = list.MyDistinct();
}
// Extension Method
public static List<Abc> MyDistinct(this List<Abc> list)
{
List<Abc> newList = new List<Abc>();
foreach (Abc item in list)
{
Abc found = newList.FirstOrDefault(x => x.Equals(item));
if (found == null)
{
newList.Add(item);
}
else
{
if (found.s != "Keep" && item.s == "Keep")
{
newList.Remove(found);
newList.Add(item);
}
}
}
return newList;
}
}
class Abc
{
public int a, b;
public string s;
public override bool Equals(object obj)
{
Abc other = obj as Abc;
return a == other.a && b == other.b;
}
public override int GetHashCode()
{
return a.GetHashCode() ^ b.GetHashCode();
}
}
Hope it will help you..