Using StructuralComparisons class for everything - c#

I had to compare equality of two two-dimensional arrays. I tried to use StructuralComparisons.StructuralEqualityComparer.Equals(obj1, obj2) and it works.
So now I wrote this method (in Helpers utility class):
public static bool Equals<T>(T obj1, T obj2)
{
return StructuralComparisons.StructuralEqualityComparer.Equals(obj1, obj2);
}
And a question: Which method should I use when I don't know whether Type T is struct (i.e. array) or class? Object.Equals or this one?

The answer is yes.
In such situations we can use StructuralComparisons comparer because it checks whether first object implements IStructuralEquatable and if it really implements, then it uses IStructuredEquatable.Equals() method, otherwise it uses obj1.Equals(obj2).
The implementation of this method is listed below
public new bool Equals(Object x, Object y) {
if (x != null) {
IStructuralEquatable seObj = x as IStructuralEquatable;
if (seObj != null){
return seObj.Equals(y, this);
}
if (y != null) {
return x.Equals(y);
} else {
return false;
}
}
if (y != null) return false;
return true;
}

Related

HashSet<T>.CreateSetComparer() cannot specify IEqualityComparer<T>, is there an alternative?

In the internal source there is such a constructor public HashSetEqualityComparer(IEqualityComparer<T> comparer) but it's internal so I can't use it.
By default, HashSet<T>.CreateSetComparer() just uses the parameterless constructor which will apply EqualityComparer<T>.Default.
Is there a way to get a HashSetEqualityComparer<T> with a IEqualityComparer<T> of choice, without copying out the code from the source?
I think best solution is using SetEquals. It does the job you need and exactly in the same way that HashSetEqualityComparer does but it will account for any custom comparers defined in the sets its comparing.
So, in your specific scenario where you want to use a HashSet<T> as a key of a dictionary, you need to implement an IEqualityComparer<HashSet<T>> that makes use of SetEquals and "borrows" the reference source of HashSetEqualityComparer.GetHashCode():
public class CustomHashSetEqualityComparer<T>
: IEqualityComparer<HashSet<T>>
{
public bool Equals(HashSet<T> x, HashSet<T> y)
{
if (ReferenceEquals(x, null))
return false;
return x.SetEquals(y);
}
public int GetHashCode(HashSet<T> set)
{
int hashCode = 0;
if (set != null)
{
foreach (T t in set)
{
hashCode = hashCode ^
(set.Comparer.GetHashCode(t) & 0x7FFFFFFF);
}
}
return hashCode;
}
}
But yes, its a small pain that there is not way to directly create a SetEqualityComparer that leverages custom comparers but this unfortunate behavior is due, IMHO, more to a bug of the existing implementation than a lack of the needed overload; there is no reason why CreateSetComparer() can't return an IEqualityComparer that actually uses the comparers of the sets its comparing as the code above demonstrates.
If I had a voice in it, CreateSetComparer() wouldn't be static method at all. It would then be obvious, or at least predictable, that whatever comparer was returned would be created with the current set's comparer.
I agree #InBetween, using SetEquals is the best way. Even if add the constructor still can not achieve what you want.
please see this code:
http://referencesource.microsoft.com/#System.Core/System/Collections/Generic/HashSet.cs,1360
Here is I try to do:
class HashSetEqualityComparerWrapper<T> : IEqualityComparer<HashSet<T>>
{
static private Type HashSetEqualityComparerType = HashSet<T>.CreateSetComparer().GetType();
private IEqualityComparer<HashSet<T>> _comparer;
public HashSetEqualityComparerWrapper()
{
_comparer = HashSet<T>.CreateSetComparer();
}
public HashSetEqualityComparerWrapper(IEqualityComparer<T> comparer)
{
_comparer = HashSet<T>.CreateSetComparer();
if (comparer != null)
{
FieldInfo m_comparer_field = HashSetEqualityComparerType.GetField("m_comparer", BindingFlags.NonPublic | BindingFlags.Instance);
m_comparer_field.SetValue(_comparer, comparer);
}
}
public bool Equals(HashSet<T> x, HashSet<T> y)
{
return _comparer.Equals(x, y);
}
public int GetHashCode(HashSet<T> obj)
{
return _comparer.GetHashCode(obj);
}
}
UPDATE
I took 5 mins to implement another version form HashSetEqualityComparer<T> source code. And rewrite the bool Equals(HashSet<T> x, HashSet<T> y) method. It is not complex. All code just copy and paste from source, I just revise a bit.
class CustomHashSetEqualityComparer<T> : IEqualityComparer<HashSet<T>>
{
private IEqualityComparer<T> m_comparer;
public CustomHashSetEqualityComparer()
{
m_comparer = EqualityComparer<T>.Default;
}
public CustomHashSetEqualityComparer(IEqualityComparer<T> comparer)
{
if (comparer == null)
{
m_comparer = EqualityComparer<T>.Default;
}
else
{
m_comparer = comparer;
}
}
// using m_comparer to keep equals properties in tact; don't want to choose one of the comparers
public bool Equals(HashSet<T> x, HashSet<T> y)
{
// http://referencesource.microsoft.com/#System.Core/System/Collections/Generic/HashSet.cs,1360
// handle null cases first
if (x == null)
{
return (y == null);
}
else if (y == null)
{
// set1 != null
return false;
}
// all comparers are the same; this is faster
if (AreEqualityComparersEqual(x, y))
{
if (x.Count != y.Count)
{
return false;
}
}
// n^2 search because items are hashed according to their respective ECs
foreach (T set2Item in y)
{
bool found = false;
foreach (T set1Item in x)
{
if (m_comparer.Equals(set2Item, set1Item))
{
found = true;
break;
}
}
if (!found)
{
return false;
}
}
return true;
}
public int GetHashCode(HashSet<T> obj)
{
int hashCode = 0;
if (obj != null)
{
foreach (T t in obj)
{
hashCode = hashCode ^ (m_comparer.GetHashCode(t) & 0x7FFFFFFF);
}
} // else returns hashcode of 0 for null hashsets
return hashCode;
}
// Equals method for the comparer itself.
public override bool Equals(Object obj)
{
CustomHashSetEqualityComparer<T> comparer = obj as CustomHashSetEqualityComparer<T>;
if (comparer == null)
{
return false;
}
return (this.m_comparer == comparer.m_comparer);
}
public override int GetHashCode()
{
return m_comparer.GetHashCode();
}
static private bool AreEqualityComparersEqual(HashSet<T> set1, HashSet<T> set2)
{
return set1.Comparer.Equals(set2.Comparer);
}
}
Avoid this class if you use custom comparers. It uses its own equality comparer to perform GetHashCode, but when performing Equals(Set1, Set2) if Set1 and Set2 have the same equality comparer, the the HashSetEqualityComparer will use the comparer of the sets. HashsetEqualityComparer will only use its own comparer for equals if Set1 and Set2 have different comparers
It gets worse. It calls HashSet.HashSetEquals, which has a bug in it (See https://referencesource.microsoft.com/#system.core/System/Collections/Generic/HashSet.cs line 1489, which is missing a if (set1.Count != set2.Count) return false before performing the subset check.
The bug is illustrated by the following program:
class Program
{
private class MyEqualityComparer : EqualityComparer<int>
{
public override bool Equals(int x, int y)
{
return x == y;
}
public override int GetHashCode(int obj)
{
return obj.GetHashCode();
}
}
static void Main(string[] args)
{
var comparer = HashSet<int>.CreateSetComparer();
var set1 = new HashSet<int>(new MyEqualityComparer()) { 1 };
var set2 = new HashSet<int> { 1, 2 };
Console.WriteLine(comparer.Equals(set1, set2));
Console.WriteLine(comparer.Equals(set2, set1)); //True!
Console.ReadKey();
}
}
Regarding other answers to this question (I don't have the rep to comment):
Wilhelm Liao: His answer also contains the bug because it's copied from the reference source
InBetween: The solution is not symmetric. CustomHashSetEqualityComparer.Equals(A, B) does not always equals CustomHashSetEqualityComparer.Equals(B, A). I would be scared of that.
I think a robust implementation should throw an exception if it encounters a set which has a different comparer to its own. It could always use its own comparer and ignore the set comparer, but that would give strange and unintuitive behaviour.
Additional to the original solution, we can simplify GetHashCode with HashCode.Combine function:
public int GetHashCode(HashSet<T> set) {
int hashCode = 0;
foreach (var item in set) {
hashCode ^= HashCode.Combine(item);
}
return hashCode;
}

Equating derived classes based on their base's Equals()

I have two classes which both derive from the same parent:
public class People{
public string BetterFoot;
public override bool Equals(object obj){
if (obj == null || this.GetType() != obj.GetType())
return false;
People o = (People)obj;
return (this.BetterFoot == o.BetterFoot);
}
public class LeftiesOrRighties: People{
public string BetterHand;
public override bool Equals(object obj){
if (obj == null || this.GetType() != obj.GetType())
return false;
LeftiesOrRighties o = (LeftiesOrRighties)obj;
return (this.BetterFoot == o.BetterFoot) &&
(this.BetterHand == o.BetterHand)
}
}
public class Ambidextrous: People{
public string FavoriteHand;
}
(There are GetHashCodes in there, too, but I know that they work.)
I'd like to compare collections of them, based on their root Equals():
ThoseOneHanded = new List<LeftiesOrRighties>(){new LeftiesOrRighties(){BetterFoot = "L"}};
ThoseTwoHanded = new List<Ambidextrous>(){new Ambidextrous(){BetterFoot = "L"}};
//using NUnit
Assert.That ((People)ThoseOneHanded[0], Is.EqualTo((People)ThoseTwoHanded[0])));
Unfortunately, this returns false.
Why? Shouldn't the casting make them (for all intents and purposes, if not exactly) the same type, and thus use the base methods? And if not, how do I truly cast the underlying type back to People?
Cast doesn't change the object itself, so the result of GetType will always be the same and so your this.GetType() != obj.GetType() will be true and so the function will return false.
The following logic could potentially gain the behaviour you want (and you don't need to cast to People)
public class People
{
public string BetterFoot;
public override bool Equals(object obj)
{
var o = obj as People;
if (o == null) return false;
return (this.BetterFoot = o.BetterFoot);
}
public class LeftiesOrRighties: People
{
public string BetterHand;
public override bool Equals(object obj)
{
var o = obj as LeftiesOrRighties;
if ( o == null) return base.Equals(obj);
return (this.BetterFoot = o.BetterFoot) && (this.BetterHand = o.BetterHand)
}
}
public class Ambidextrous: People
{
public string FavoriteHand;
}
As Bob Vale pointed out, the cast does not change type.
The standard solution used across the .NET Framework is to use custom object implementing IEqualityComparer or its generic variant. Then your compare/find method takes 2 objects/collections and uses comparer to perform the custom comparison.
I.e. many LINQ methods take custom compare to find/filter objects like
Enumerable.Distinct
public static IEnumerable<TSource> Distinct<TSource>(
this IEnumerable<TSource> source,
IEqualityComparer<TSource> comparer
)
Sample comparer:
class Last3BitsComparer : IEqualityComparer<int>
{
public bool Equals(int b1, int b2)
{
return (b1 & 3) == (b2 & 3);
}
public int GetHashCode(int bx)
{
return bx & 3;
}
}

interface<T> methods from the implementing classes without a reference

I have a generic interface, and a few classes implement it.
then from a global place, I want to use methods from that interface,
yet, I don't know their compiled generic type, so the reference is only their object's class, as showing in runtime. (so I can't get access to the interface methods)
a few questions:
Is it possible to use them?
should I design it without generics?
what is the purpose of generic interfaces if I can't use them at runtime?
can generics out/in or dynamic help in that situation?
edit: some example code
public interface IMyInterface<T>
where T: class, new()
{
void Delete (T obj);
}
public class trigger {}
public class triggervm : IMyInterface<trigger>
{
List<trigger> _trigList = new List<trigger>()
public void Delete (trigger obj)
{
_trigList.Remove (obj);
}
}
now, say I want to check, and then use the method Delete, from a "global" place:
if (chosenItem is IMyInterface<???>)
{
var item = chosenItem as IMyInterface<???>;
item.Delete(someObj);
}
Here's an example of how you can use the functions of a generic interface without having to know what the generic types are when writing the code.
The basic idea is to call your own generic function (in this case CompareValuesInternal) and use reflection to extract the appropriate type information to pass along with the call.
sm_compare_values_info = typeof(YourType).GetMethod("CompareValuesInternal", BindingFlags.NonPublic | BindingFlags.Static);
static public bool CompareValues(object x, object y)
{
bool result = true;
if ((x == null && y != null) || (x != null && y == null))
{
result = false;
}
else if (x == null && y == null)
{
result = true;
}
else if (x is IComparer)
{
result = ((x as IComparer).Compare(x, y) == 0);
}
else if (x is IComparable)
{
result = ((x as IComparable).CompareTo(y) == 0);
}
else if (x is IEqualityComparer)
{
result = (x as IEqualityComparer).Equals(x, y);
}
else if (x.GetType() != y.GetType())
{
result = false;
}
else
{
//----IMPORTANT PART----
MethodInfo info = sm_compare_values_info.MakeGenericMethod(x.GetType());
result = (bool)info.Invoke(null, new object[] { x, y });
}
return result;
}
static protected bool CompareValuesInternal<T>(T x, T y)
{
bool result = false;
if (x is IEqualityComparer<T>)
{
result = (x as IEqualityComparer<T>).Equals(x, y);
}
else if (x is IEquatable<T>)
{
result = (x as IEquatable<T>).Equals(y);
}
else if (x is IComparable<T>)
{
result = ((x as IComparable<T>).CompareTo(y) == 0);
}
else if (x is IComparer<T>)
{
result = ((x as IComparer<T>).Compare(x, y) == 0);
}
return result;
}
Yes, using dynamic can be the simplest and best way to cope with this issue. Jon Skeet's C# in action mentions this as well in the section about dynamics.
As others said, more code less english and we all can narrow this down here.
like thomas suggested, I use dynamic,
and like "RedHat" suggested, I have the enclosing class inherit from both my interface (IClipboard<T>) and a parent interface (IClippable) that is just a "grouping" interface.
myinterface inherits from the grouping interface, so any class that implements myinterface also matches the grouping one.
so I can check if the selected item is IClippable.
the cleanest I could get with my current knowledge of the language.
better support in C# would be nice.
interface IInterface<T>
{
Type GetMyType();
}
class MyClass1 : IInterface<int>
{
public Type GetMyType()
{
return typeof(int);//each subclass must be return own generic type
}
}
static void Main()
{
new MyClass1().GetMyType()==typeof(int);//Is True
}

((System.Object)p == null)

Why do this:
// If parameter cannot be cast to Point return false.
TwoDPoint p = obj as TwoDPoint;
if ((System.Object)p == null)
{
return false;
}
Instead of this:
// If parameter cannot be cast to Point return false.
TwoDPoint p = obj as TwoDPoint;
if (p == null)
{
return false;
}
I don't understand why you'd ever write ((System.Object)p)?
Regards,
Dan
You cast to object when you don't know or can't be sure whether the original class has overridden operator ==:
using System;
class AlwaysEqual
{
public static bool operator ==(AlwaysEqual a, AlwaysEqual b)
{
return true;
}
public static bool operator !=(AlwaysEqual a, AlwaysEqual b)
{
return true;
}
}
class Program
{
static void Main()
{
object o = new AlwaysEqual();
AlwaysEqual ae = o as AlwaysEqual;
if (ae == null)
{
Console.WriteLine("ae is null");
}
if ((object)ae == null)
{
Console.WriteLine("(object)ae is null");
}
}
}
This code outputs only "ae is null", which is obviously not the case. The cast to object avoids the AlwaysEqual class's operator == and is therefore a true reference check against null.
Every object in .NET is derived from System.Object so there is no need for explicit cast.
And even more concise would be:
if (!(obj is TwoDPoint)) {
return false;
}
Plainly speaking, It's pointless. Null can always be assigned(except for non-nullables such as ints and structs) regardless of type so it can always be checked for. The cast is not necessary
If TwoDPoint is a non-nullable type such as a struct then indeed it may have a point. The (System.Object) cache would effectively box the struct into a nullable object. But if that was the case then obj as TwoDPoint would not be valid. You would need obj as TwoDPoint? to make it nullable. (can't use as with non-nullables)
It makes total sense if that code is inside Object.Equals override and you don't want to invoke the equality operator (which might, for example, erroneously call Equals). Casting to object allows to call standard equality operator, which compares references.
Normally, you would use Object.ReferenceEquals to compare an instance of an object to null inside Equals override.
For example, this would cause a stack overflow:
public class Point {
public override bool Equals (object other) {
var otherPoint = other as Point;
if (other == null)
return false;
//...
}
public static bool operator == (Point l, Point r) {
//...
//null checks
if (!l.Equals(r))
return false;
}
}
In the above example equality operator calls Equals and because otherPoint variable is of type Point, it would invoke the equality operator, causing infinite recursion.
Normally, when you override Equals and define the equality operator, you would put the comparison logic in the operator and invoke that from the Equals override. Bear in mind that it's recommended for the class to be immutable if both are overridden.
public class Point {
public override bool Equals (object other) {
var otherPoint = other as Point;
return this == otherPoint;
}
//must override GetHashCode() as well
public static bool operator == (Point l, Point r) {
if (Object.ReferenceEquals(l, null) && Object.ReferenceEquals(r, null))
return true;
if (Object.ReferenceEquals(l, null) || Object.ReferenceEquals(r, null))
return false;
//actual equality checks
}
public static bool operator != (Point l, Point r) {
return !(l==r);
}
}

Overriding Equals and comparing to string

I've defined a C# class with a string member. For all intents an purposes, think of this class as being a subclass of string (except that's not allowed). I'm using it to represent a strongly typed string field that matches a specific format (I've simplified this significantly).
public class field
{
private readonly string m_field;
public field(string init_value)
{
//Check the syntax for errors
if (CheckSyntax(init_value))
{
m_field = init_value;
}
else
{
throw new ArgumentOutOfRangeException();
}
}
public override string ToString()
{
return m_field;
}
}
Now, I want to be able to compare this class directly to any other string (object or literal). Therefore, I implemented the following in the class:
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
return this.m_field == obj.ToString();
}
public override int GetHashCode()
{
return this.m_field.GetHashCode();
}
public static bool operator ==(field x, Object y)
{
if ((object)x == null && y == null)
{
return true;
}
else if ((object)x == null || y == null)
{
return false;
}
else
{
return (x.m_field == y.ToString());
}
}
public static bool operator !=(field x, Object y)
{
return !(x == y);
}
Now when I'm writing a unit test, depending on the order that I'm passing in the arguments to Assert.AreEqual, I get different results:
string valid = "Some String";
field target = new field(valid);
Assert.AreEqual(target, valid); // PASSES
Assert.AreEqual(valid, target); // FAILS
I'm assuming this is because in the first assert, it's calling field.Equals() and in the second it's calling String.Equals(). Obviously I'm approaching this from the wrong angle. Can anyone give me some insight?
One other thing. I can't use a struct here (value type) because in my actual case I'm defining all this in a base class and inheriting from it.
Basically you can't do what you want to - there's no way you can make string recognise your class for equality purposes. You'll never be able to make it reflexive - you'll never be able to make it obey the contract of object.Equals.
I would personally try to redesign it so that you didn't have the validation as part of the type itself - make it part of the relevant properties of the business entities (or whatever they are).
This is described in detail in Effective Java as Item 8: Obey the general contract when overriding equals.
The equals method implements an equivalence relation.
It is Reflexive, Symmetric, Transitive, Consistent, and for any non-null reference x, x.equals(null) must return false. The example cited to break symmetry is similar to yours.
field class is aware of string class, but the built-in string class is not aware of field. This a one-way interoperability, and should be removed.
I would discourage anyone using your field class implicitly as a String, and force this type of usage:
string valid = "Some String";
field target = new field(valid);
Assert.AreEqual(target.toString(), valid);
Assert.AreEqual(valid, target.toString());
Based on everyone's feedback, and my own needs, here's what I'm putting forward as a possible solution (I'm modifying the Equals method as follows):
public override bool Equals(Object obj)
{
if (obj == null)
{
return false;
}
field f = obj as field;
if (f != null)
{
return this == f;
}
else
{
return obj.Equals(this);
}
}
This seems to allow its correct use in dictionary and collection classes that rely on the Equals and GetHashCode methods for determining if the value already exists.
Also, now these both fail:
string valid = "Some String";
field target = new field(valid);
Assert.AreEqual(target, valid); // FAILS
Assert.AreEqual(valid, target); // FAILS
And these both pass:
string valid = "Some String";
field target = new field(valid);
Assert.AreEqual(target.ToString(), valid); // PASSES
Assert.AreEqual(valid, target.ToString()); // PASSES
And these both pass:
field f1 = new field("Some String");
field f2 = new field("Some String");
Assert.AreEqual(f1, f2); // PASSES
Assert.AreEqual(f2, f1); // PASSES
This is String#Equals
public override bool Equals(object obj)
{
string strB = obj as string;
if ((strB == null) && (this != null))
{
return false;
}
return EqualsHelper(this, strB);
}
Supplying an argument other than a String to String#Equals is going to return false. I'd suggest a 'rethink' to get around this.
I suggest using object.ReferenceEquals() if you are internally trying to validate whether x or y is null.
public static bool operator ==(field x, Object y)
{
if (object.ReferenceEquals(x, null) && object.ReferenceEquals(y, null))
{
return true;
}
else if (object.ReferenceEquals(x, null) || object.ReferenceEquals(y, null))
{
return false;
}
else
{
return (x.m_field == y.ToString());
}
}

Categories

Resources