C# Queue problem - c#

Suppose I have a class
XYNode
{
protected int mX;
protected int mY;
}
and a queue
Queue<XyNode> testQueue = new Queue<XYNode>();
I want to check if a node with that specific x and y coordinate is already in the queue.
The following obviously doesn't work :
testQueue.Contains(new XYNode(testX, testY))
because even if a node with those coordinates is in the queue, we're testing against a different XYNode object so it will always return false.
What's the right solution ?

The simplest way is to override Equals so that one XYNode knows whether it's equal to another XYNode. You should override GetHashCode() at the same time, and possibly also implement IEquatable<XYNode> to allow a strongly-typed equality comparison.
Alternatively, you could write an IEqualityComparer<XYNode> implementation to compare any two nodes and return whether or not they're the same - and then pass that into the call to the appropriate overload of the Contains extension method defined in Enumerable (assuming you're using .NET 3.5).
Further things to consider:
Could you use private fields instead of protected ones?
Could your class be sealed?
Could your class be immutable?
Should your class perhaps be a struct instead? (Judgement call...)
Should you overload the == and != operators?

To illustrate Jon Skeet's ... original ... answer:
class XYNode {
protected int mX;
protected int mY;
public override bool Equals(Object obj) {
if (obj == null || this.GetType() != obj.GetType()) { return false; }
XYNode otherNode = (XYNode)obj;
return (this.mX == other.mX) && (this.mY == other.mY);
}
}
This is a pretty simplistic solution. There are a lot of additional factors to consider, which Jon has already mentioned.

You could simply iterate with a foreach and check the X and Y of your XYNode on every element.

Related

How to compare two objects when you can't override Equals?

I have an object modelNoBend of type CalculationModel and I have serialized it into a JSON and saved it in a .txt file using the below:
private static void GenerateTextFileNoBend(string path, CalculationModel model)
{
if (!File.Exists(path)) {
using (var file = File.CreateText(path + "noBend.txt")) {
var json = JsonConvert.SerializeObject(model);
file.Write(json);
}
}
}
Then, I wanted to deserialize that JSON and check with the original object whether they are the same or not.
static void Main(string[] args)
{
GenerateTextFileNoBend(path, modelNoBend);
var jsonText = File.ReadAllText(#"D:\5113\noBend.txt");
CalculationModel model = JsonConvert.DeserializeObject<CalculationModel>(jsonText);
string one = JsonConvert.SerializeObject(modelNoBend);
string two = JsonConvert.SerializeObject(model);
if (model.Equals(modelNoBend)) {
Console.Write("Yes");
}
if (one.Equals(two)) {
Console.Write("Yes");
}
}
if (model.Equals(modelNoBend)) - False
if (one.Equals(two)) - True
If I compare the two objects, .Equals() returns false. However, if I serialize them both once again and compare the strings, the if goes on the true branch.
Obviously, something that I have missed out on the last post is that I can not edit the CalculationModel class. This means that I can not follow the answers in this question, since I can not override Equals, nor use something else like IEqualityComparer as it requires the class to implement IComparable.
Is there any workaround for this, without me having to touch that class?
Well, since you don't override Equals and GetHashCode then model and modelNoBend are
compared by their references. model and modelNoBend don't share the same reference, that's
why they considered being unequal.
You can't implement custom Equals and GetHashCode but you can implement comparer:
public class CalculationModelComparer : IEqualityComparer<CalculationModel> {
public bool Equals(CalculationModel x, CalculationModel y) {
if (ReferenceEquals(x, y))
return true;
if (null == x || null == y)
return false;
// I have nothing but serialization data to compare
//TODO: put smarter code: compare properties and fields here
return string.Equals(
JsonConvert.SerializeObject(x),
JsonConvert.SerializeObject(y));
}
public int GetHashCode(CalculationModel obj) {
if (null == obj)
return 0;
// I have nothing but serialization data to compare and
// serialization is a long process... So we can put either 1 or
// JsonConvert.SerializeObject(obj).GetHashCode();
//TODO: put smarter code: compute hash from properties and fields
return 1;
}
public static IEqualityComparer<CalculationModel> Instance {get} =
new CalculationModelComparer();
}
Then use it:
if (CalculationModelComparer.Instance.Equals(model, modelNoBend)) {
...
}
I hope this answer does not sound flippant; it is not meant to be.
If your use case is just this small case, or the class being checked for equality is reasonably small in terms of fields, it's totally legit to just code a method that compares the fields as needed.
There are plenty of cases that support something like this, especially in tight loops for performance.
That said #Dmitry's answer is correct. I offer this as an alternative when it makes sense.

IComparable in C#

I have an object called Shape which contains a public int[,] coordinate { get; set; } field.
I have a separate class which has a collection of Shape objects. At a particular point, I wish to check:
if(shapes.Contains(shape))
{
// DoSomething
}
So in the Shape class I have added the IComparable reference and inserted the CompareTo method:
public int CompareTo(Shape other)
{
return this.coordinate.Equals(other.coordinate);
}
I am however getting an error:
Cannot implicitly convert type 'bool' to 'int'
How do I therefore phrase the return so that it returns an int and not a bool as it is doing so at the moment?
UPDATE
If I change the return code to:
return this.coordinate.CompareTo(other.coordinate);
I get the following error mesage:
Error 1 'ShapeD.Game_Objects.Shape' does not implement interface member 'System.IComparable.CompareTo(ShapeD.Game_Objects.Shape)'. 'ShapeD.Game_Objects.Shape.CompareTo(ShapeD.Game_Objects.Shape)' cannot implement 'System.IComparable.CompareTo(ShapeD.Game_Objects.Shape)' because it does not have the matching return type of 'int'. C:\Users\Usmaan\Documents\Visual Studio 2012\Projects\ShapeD\ShapeD\ShapeD\Game Objects\Shape.cs 10 18 ShapeD
IComparable implies, that two object can be compared in a sense, that you can tell which object has "higher value". It is generally used for sorting purposes. You should override Equals method instead .You should also use Point struct instead of array.
class Shape : IEquatable<Shape>
{
public Point coordinate { get; set; }
public bool Equals(Shape other)
{
if (other == null) return false;
return coordinate.Equals(other.coordinate);
}
public override bool Equals(object other)
{
if (other == null) return false;
if (ReferenceEquals(this, other)) return true;
var shape = other as Shape;
return Equals(shape);
}
public override int GetHashCode()
{
return coordinate.GetHashCode()
}
}
Since you only want to check for equality implement IEquatable interface not IComparable.
IComparable is used for sorting purpose
public bool Equals(Shape s)
{
int count=0;
int[] temp1=new int[this.coordinate.Length];
foreach(int x in this.coordinate)temp1[count++]=x;//convert to single dimention
count=0;
int[] temp2=new int[s.coordinate.Length];
foreach(int x in s.coordinate)temp2[count++]=x;//convert to single dimention
return temp1.SequenceEqual(temp2);//check if they are equal
}
NOTE
IEquatable should be implemented for any object that might be stored in a generic collection else you would have to also override Object's Equals method.Also as pointed out in other ans use Point struct instead of multidimentional array
For performing Contains check you need to override Equals operator in Shape class.
Resurrecting an old question only because it can still cause google hits despite some really poor answers.
You should not be using either CompareTo or Equals.
Neither of these fits with what you are trying to do and will only cause confusion, as evidenced by the answers written here.
Write your own method called something like IntersectsWith.
Have a look into any decent geometry library (e.g. boost if you're happy pulling from c++) as how to go about doing this.
As to casting from bool to int, this can be easily done by using the bool with the ? ternary operator.

Comparing two instances of a class

I have a class like this
public class TestData
{
public string Name {get;set;}
public string type {get;set;}
public List<string> Members = new List<string>();
public void AddMembers(string[] members)
{
Members.AddRange(members);
}
}
I want to know if it is possible to directly compare to instances of this class to eachother and find out they are exactly the same? what is the mechanism? I am looking gor something like if(testData1 == testData2) //Do Something And if not, how to do so?
You should implement the IEquatable<T> interface on your class, which will allow you to define your equality-logic.
Actually, you should override the Equals method as well.
public class TestData : IEquatable<TestData>
{
public string Name {get;set;}
public string type {get;set;}
public List<string> Members = new List<string>();
public void AddMembers(string[] members)
{
Members.AddRange(members);
}
// Overriding Equals member method, which will call the IEquatable implementation
// if appropriate.
public override bool Equals( Object obj )
{
var other = obj as TestData;
if( other == null ) return false;
return Equals (other);
}
public override int GetHashCode()
{
// Provide own implementation
}
// This is the method that must be implemented to conform to the
// IEquatable contract
public bool Equals( TestData other )
{
if( other == null )
{
return false;
}
if( ReferenceEquals (this, other) )
{
return true;
}
// You can also use a specific StringComparer instead of EqualityComparer<string>
// Check out the specific implementations (StringComparer.CurrentCulture, e.a.).
if( EqualityComparer<string>.Default.Compare (Name, other.Name) == false )
{
return false;
}
...
// To compare the members array, you could perhaps use the
// [SequenceEquals][2] method. But, be aware that [] {"a", "b"} will not
// be considerd equal as [] {"b", "a"}
return true;
}
}
One way of doing it is to implement IEquatable<T>
public class TestData : IEquatable<TestData>
{
public string Name {get;set;}
public string type {get;set;}
public List<string> Members = new List<string>();
public void AddMembers(string[] members)
{
Members.AddRange(members);
}
public bool Equals(TestData other)
{
if (this.Name != other.Name) return false;
if (this.type != other.type) return false;
// TODO: Compare Members and return false if not the same
return true;
}
}
if (testData1.Equals(testData2))
// classes are the same
You can also just override the Equals(object) method (from System.Object), if you do this you should also override GetHashCode see here
There are three ways objects of some reference type T can be compared to each other:
With the object.Equals method
With an implementation of IEquatable<T>.Equals (only for types that implement IEquatable<T>)
With the comparison operator ==
Furthermore, there are two possibilities for each of these cases:
The static type of the objects being compared is T (or some other base of T)
The static type of the objects being compared is object
The rules you absolutely need to know are:
The default for both Equals and operator== is to test for reference equality
Implementations of Equals will work correctly no matter what the static type of the objects being compared is
IEquatable<T>.Equals should always behave the same as object.Equals, but if the static type of the objects is T it will offer slightly better performance
So what does all of this mean in practice?
As a rule of thumb you should use Equals to check for equality (overriding object.Equals as necessary) and implement IEquatable<T> as well to provide slightly better performance. In this case object.Equals should be implemented in terms of IEquatable<T>.Equals.
For some specific types (such as System.String) it's also acceptable to use operator==, although you have to be careful not to make "polymorphic comparisons". The Equals methods, on the other hand, will work correctly even if you do make such comparisons.
You can see an example of polymorphic comparison and why it can be a problem here.
Finally, never forget that if you override object.Equals you must also override object.GetHashCode accordingly.
I see many good answers here but just in case you want the comparison to work like
if(testData1 == testData2) // DoSomething
instead of using Equals function you can override == and != operators:
public static bool operator == (TestData left, TestData right)
{
bool comparison = true; //Make the desired comparison
return comparison;
}
public static bool operator != (TestData left, TestData right)
{
return !(left == right);
}
You can override the equals method and inside it manually compare the objects
Also take a look at Guidelines for Overloading Equals() and Operator ==
You will need to define the rules that make object A equal to object B and then override the Equals operator for this type.
http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx
First of all equality is difficult to define and only you can define as to what equality means for you
Does it means members have same value
Or they are pointing to same location.
Here is a discussion and an answer here
What is "Best Practice" For Comparing Two Instances of a Reference Type?
Implement the IEquatable<T> interface. This defines a generalized method that a value type or class implements to create a type-specific method for determining equality of instances. More information here:
http://msdn.microsoft.com/en-us/library/ms131187.aspx

Distinct() returns duplicates with a user-defined type

I'm trying to write a Linq query which returns an array of objects, with unique values in their constructors. For integer types, Distinct returns only one copy of each value, but when I try creating my list of objects, things fall apart. I suspect it's a problem with the equality operator for my class, but when I set a breakpoint, it's never hit.
Filtering out the duplicate int in a sub-expression solves the problem, and also saves me from constructing objects that will be immediately discarded, but I'm curious why this version doesn't work.
UPDATE: 11:04 PM Several folks have pointed out that MyType doesn't override GetHashCode(). I'm afraid I oversimplified the example. The original MyType does indeed implement it. I've added it below, modified only to put the hash code in a temp variable before returning it.
Running through the debugger, I see that all five invocations of GetHashCode return a different value. And since MyType only inherits from Object, this is presumably the same behavior Object would exhibit.
Would I be correct then to conclude that the hash should instead be based on the contents of Value? This was my first attempt at overriding operators, and at the time, it didn't appear that GetHashCode needed to be particularly fancy. (This is the first time one of my equality checks didn't seem to work properly.)
class Program
{
static void Main(string[] args)
{
int[] list = { 1, 3, 4, 4, 5 };
int[] list2 =
(from value in list
select value).Distinct().ToArray(); // One copy of each value.
MyType[] distinct =
(from value in list
select new MyType(value)).Distinct().ToArray(); // Two objects created with 4.
Array.ForEach(distinct, value => Console.WriteLine(value));
}
}
class MyType
{
public int Value { get; private set; }
public MyType(int arg)
{
Value = arg;
}
public override int GetHashCode()
{
int retval = base.GetHashCode();
return retval;
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
MyType rhs = obj as MyType;
if ((Object)rhs == null)
return false;
return this == rhs;
}
public static bool operator ==(MyType lhs, MyType rhs)
{
bool result;
if ((Object)lhs != null && (Object)rhs != null)
result = lhs.Value == rhs.Value;
else
result = (Object)lhs == (Object)rhs;
return result;
}
public static bool operator !=(MyType lhs, MyType rhs)
{
return !(lhs == rhs);
}
}
You need to override GetHashCode() in your class. GetHashCode must be implemented in tandem with Equals overloads. It is common for code to check for hashcode equality before calling Equals. That's why your Equals implementation is not getting called.
Your suspicion is correct,it is the equality which currently just checks the object references. Even your implementation does not do anything extra, change it to this:
public override bool Equals(object obj)
{
if (obj == null)
return false;
MyType rhs = obj as MyType;
if ((Object)rhs == null)
return false;
return this.Value == rhs.Value;
}
In you equality method you are still testing for reference equality, rather than semantic equality, eg on this line:
result = (Object)lhs == (Object)rhs
you are just comparing two object references which, even if they hold exactly the same data, are still not the same object. Instead, your test for equality needs to compare one or more properties of your object. For instance, if your object had an ID property, and objects with the same ID should be considered semantically equivalent, then you could do this:
result = lhs.ID == rhs.ID
Note that overriding Equals() means you should also override GetHashCode(), which is another kettle of fish, and can be quite difficult to do correctly.
You need to implement GetHashCode().
It seems that a simple Distinct operation can be implemented more elegantly as follows:
var distinct = items.GroupBy(x => x.ID).Select(x => x.First());
where ID is the property that determines if two objects are semantically equivalent. From the confusion here (including that of myself), the default implementation of Distinct() seems to be a little convoluted.
I think MyType needs to implement IEquatable for this to work.
The other answers have pretty much covered the fact that you need to implement Equals and GetHashCode correctly, but as a side note you may be interested to know that anonymous types have these values implemented automatically:
var distinct =
(from value in list
select new {Value = value}).Distinct().ToArray();
So without ever having to define this class, you automatically get the Equals and GetHashCode behavior you're looking for. Cool, eh?

How do I implement IEqualityComparer on an immutable generic Pair struct?

Currently I have this (edited after reading advice):
struct Pair<T, K> : IEqualityComparer<Pair<T, K>>
{
readonly private T _first;
readonly private K _second;
public Pair(T first, K second)
{
_first = first;
_second = second;
}
public T First { get { return _first; } }
public K Second { get { return _second; } }
#region IEqualityComparer<Pair<T,K>> Members
public bool Equals(Pair<T, K> x, Pair<T, K> y)
{
return x.GetHashCode(x) == y.GetHashCode(y);
}
public int GetHashCode(Pair<T, K> obj)
{
int hashCode = obj.First == null ? 0 : obj._first.GetHashCode();
hashCode ^= obj.Second == null ? 0 : obj._second.GetHashCode();
return hashCode;
}
#endregion
public override int GetHashCode()
{
return this.GetHashCode(this);
}
public override bool Equals(object obj)
{
return (obj != null) &&
(obj is Pair<T, K>) &&
this.Equals(this, (Pair<T, K>) obj);
}
}
The problem is that First and Second may not be reference types (VS actually warns me about this), but the code still compiles. Should I cast them (First and Second) to objects before I compare them, or is there a better way to do this?
Edit:
Note that I want this struct to support value and reference types (in other words, constraining by class is not a valid solution)
Edit 2:
As to what I'm trying to achieve, I want this to work in a Dictionary. Secondly, SRP isn't important to me right now because that isn't really the essence of this problem - it can always be refactored later. Thirdly, comparing to default(T) will not work in lieu of comparing to null - try it.
Your IEqualityComparer implementation should be a different class (and definately not a struct as you want to reuse the reference).
Also, your hashcode should never be cached, as the default GetHashcode implementation for a struct (which you do not override) will take that member into account.
It looks like you need IEquatable instead:
internal struct Pair<T, K> : IEquatable<Pair<T, K>>
{
private readonly T _first;
private readonly K _second;
public Pair(T first, K second)
{
_first = first;
_second = second;
}
public T First
{
get { return _first; }
}
public K Second
{
get { return _second; }
}
public bool Equals(Pair<T, K> obj)
{
return Equals(obj._first, _first) && Equals(obj._second, _second);
}
public override bool Equals(object obj)
{
return obj is Pair<T, K> && Equals((Pair<T, K>) obj);
}
public override int GetHashCode()
{
unchecked
{
return (_first != null ? _first.GetHashCode() * 397 : 0) ^ (_second != null ? _second.GetHashCode() : 0);
}
}
}
If you use hashcodes in comparing methods, you should check for "realy value" if the hash codes are same.
bool result = ( x._hashCode == y._hashCode );
if ( result ) { result = ( x._first == y._first && x._second == y._second ); }
// OR?: if ( result ) { result = object.Equals( x._first, y._first ) && object.Equals( x._second, y._second ); }
// OR?: if ( result ) { result = object.ReferenceEquals( x._first, y._first ) && object.Equals( x._second, y._second ); }
return result;
But there is littlebit problem with comparing "_first" and "_second" fields.
By default reference types uses fore equality comparing "object.ReferenceEquals" method, bud they can override them. So the correct solution depends on the "what exactly should do" the your comparing method. Should use "Equals" method of the "_first" & "_second" fields, or object.ReferenceEquals ? Or something more complex?
Regarding the warning, you can use default(T) and default(K) instead of null.
I can't see what you're trying to achieve, but you shouldn't be using the hashcode to compare for equality - there is no guarantee that two different objects won't have the same hashcode. Also even though your struct is immutable, the members _first and _second aren't.
First of all this code violates SRP principle. Pair class used to hold pairs if items, right? It's incorrect to delegate equality comparing functionality to it.
Next let take a look at your code:
Equals method will fail if one of the arguments is null - no good. Equals uses hash code of Pair class, but take a look at the definition of GetHashCode, it just a combination of pair members hash codes - it's has nothing to do with equality of items. I would expect that Equals method will compare actual data. I'm too busy at the moment to provide correct implementation, unfortunately. But from the first look, you code seems to be wrong. It would be better if you provide us description of what you want to achieve. I'm sure SO members will be able to give you some advices.
Might I suggest the use of Lambda expressions as a parameter ?
this would allow you to specify how to compare the internal generic types.
I don't get any warning when compiling about this but I assume you are talking about the == null comparison? A cast seems like it would make this all somewhat cleaner, yes.
PS. You really should use a separate class for the comparer. This class that fills two roles (being a pair and comparing pairs) is plain ugly.

Categories

Resources