Why is this not working? (Generic Equals Helper) - c#

SOLVED!
This works, I need to tell the compiler that T implements IEquatable of course...
public static bool secureEquals<T>(T obj1, object obj2)
where T: class, IEquatable<T>
{...
public static bool secureEquals<T>(T obj1, T obj2)
where T: class, IEquatable<T>
{....
Question:
I tried to put repeated functionality of IEquatable implementations and Equals overrides into a separate static class like so:
public static class EqualsHelper
{
public static bool secureEquals<T>(T obj1, object obj2)
where T : class
{
if (obj2 is T)
{
return secureEquals(obj1, obj2 as T);
}
else
{
return false;
}
}
public static bool secureEquals<T>(T obj1, T obj2)
{
if (obj1 == null)
{
if (obj2 != null)
return false;
}
else
{
if (!obj1.Equals(obj2)) //this calls Dummy.Equals(object other)!
return false;
}
return true;
}
public static bool secureEquals(double[] obj1, double[] obj2)
{
if (obj1.Length != obj2.Length)
return false;
for (int i = 0; i < obj1.Length; ++i)
{
if (obj1[i] != obj2[i])//ok for doubles if they are generated in the same way? I guess so!
return false;
}
return true;
}
public class Dummy : IEquatable<Dummy>
{
public Dummy(string member)
{
_member = member;
}
private string _member;
public virtual bool Equals(Dummy other)
{
return this._member == other._member;
}
public override bool Equals(object other)
{
return EqualsHelper.secureEquals(this, other);
}
}
static void Main(string[] args)
{
Dummy d1 = new Dummy("Hugo");
Dummy d2 = new Dummy("Hugo");
object d2obj = (object)d2;
bool ret = d1.Equals(d2obj);
}
The idea was:
d1.Equals(d2obj) calls Dummy.Equals(object) calls EqualsHelper.secureEquals(T, obj) calls EqualsHelper.secureEquals(T, T) calls Dummy.Equals(Dummy).
The last call however calls Dummy.Equals(object), even though everything is typed to T there.
What am I missing?
PS: I know that replacing the call with:
if (!((IEquatable<T>)obj1).Equals(obj2)) //this calls Dummy.Equals(object other)!
does the trick, but why is it not working otherwise?

Why: because method invoke here is static typed, and the only available Equals involving a T with no generic constraint is object.Equals(object). The exact same IL has to be able to handle every T - C# generics are not like C++ templates; no per-T overload resolution occurs.
As an aside: you might also want to look at EqualityComparer<T>.Default.Equals(obj1,obj2), which will handle IEquatable<T>, Nullable<T>, etc automatically:
public static bool secureEquals<T>(T obj1, object obj2) where T : class
{
return EqualityComparer<T>.Default.Equals(obj1, obj2 as T);
}

The Equals overload within EqualsHelper.secureEquals is resolved when EqualsHelper is compiled - and that code doesn't know whether T implements IComparable<T> or not, so all that's left is Equals(Object). You can add a constraint to T which would make it use the right overload:
public static bool SecureEquals<T>(T obj1, T obj2) where T : IEquatable<T>
Of course, this would limit the classes with which you could use it.
(As an aside, note that I've renamed secureEquals to SecureEquals to comply with .NET naming conventions. I'd also not use the word "secure" here at all personally - there's nothing security-sensitive here.)

Because in your secureEquals you have no constraints, and compiler always assumes Object.Equals exist. Add interface constraint for your T.

Related

Declaring generic Dictionary with bounded type

I need to declare a Dictionary having a Type as key and an instance as value.
I need to limit key Type to a certain class hierarchy.
For a Java Map, I can do something like:
Map<Class<? extends MySuperClass>, ? extends MySuperClass>
How can I achieve this in C#?
Do not expose Dictionary directly, this way you can control manually when to add
public void AddToDictionary(Type key, object value)
{
if(!key.IsAssignableFrom(typeof(SomeBaseClass))
throw new ArgumentException("Must be an inherited from SomeBaseClass type");
dictionary.Add(key, value);
}
I think Sinatr's approach of exposing a method for adding to the dictionary instead of the dictionary itself is a very good idea. The only downside is that you get no compile time safety; if some code added an object of the wrong type you wouldn't find out till runtime.
Using generics, however, we can tweak the method so that adding objects is foolproof:
public void AddToDictionary<T>(T value) where T: MySuperClass
{
dict.Add(typeof(T), value);
}
Now it is impossible to write a program that adds objects of the wrong type and still compiles.
You could use typeof to get the type of the class so something like:
Map<System.Type, object>
I am not sure how you would enforce the extends for this. That should probably happen as a test before adding to the map.
You could:
public class MyType<TBase>
{
private Type Value;
protected MyType()
{
}
public static implicit operator Type(MyType<TBase> type)
{
return type.Value;
}
public static implicit operator MyType<TBase>(Type type)
{
if (type == null)
{
throw new ArgumentNullException();
}
if (!typeof(TBase).IsAssignableFrom(type))
{
throw new ArgumentException();
}
return new MyType<TBase> { Value = type };
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
var type = obj as MyType<TBase>;
return type != null && Value.Equals(type.Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public override string ToString()
{
return Value.ToString();
}
}
and then:
Dictionary<MyType<MySuperClass>, MySuperClass> dict = new Dictionary<MyType<MySuperClass>, MySuperClass>();
dict.Add(typeof(MyClass1), new MyClass1());
The MyType has implicit operators from/to Type, so it is quite simple to use. You simply cast a Type to a MyType (or a MyType to a Type) and it just works. Example of TryGetValue():
MySuperClass ms;
if (!dict.TryGetValue(typeof(MyClass1), out ms))
{
throw new Exception();
}
Note that the checks are done at runtime!

C# generics class operators not working

I have a problem with generic. When I try to use less operators in generic, their call is not happening. But it works with the method Equals.
That is a some test class:
public class Test
{
public int i;
static public Boolean operator ==(Test obj1, Test obj2)
{
Console.WriteLine("operator ==");
return obj1.i == obj2.i;
}
static public Boolean operator !=(Test obj1, Test obj2)
{
Console.WriteLine("operator !=");
return obj1.i != obj2.i;
}
public override bool Equals(object obj)
{
Console.WriteLine("operator equals");
return this == (Test)obj;
}
public override int GetHashCode()
{
Console.WriteLine("HashCode");
return 5;
}
}
And class Checker:
public class Checker
{
public Boolean TestGeneric<T>(T Left, T Right) where T : class
{
return Left == Right; //not work override operators
return Left.Equals(Right); //work fine
}
}
Small testing:
Test left = new Test() { i = 4 };
Test right = new Test() { i = 4 };
var checker = new Checker();
Console.WriteLine(checker.TestGeneric<Test>(left, right));
Console.ReadKey();
How I can use less operators in class Test from generic?
Overloaded operators are static methods, so they don't participate in polymorphism; they are resolved statically at compile time, based on the known type of the operands.
In a generic method, the compiler can't know that T will be Test (since it could actually be anything else), so it uses the most general definition of ==, which is reference comparison.
Note that if you add a constraint on the generic method to force T to be Test or a subclass of Test, it will work as expected, but of course it won't work anymore for other types...
This now works in C# 11 / .NET 7 (or above):
public class Test : IEqualityOperators<Test, Test, bool>
{ /* no changes except ^^^ addition */ }
public bool TestGeneric<T>(T Left, T Right) where T : IEqualityOperators<T, T, bool>
{
return Left == Right; // does what you expect
}

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.

How to achieve operator overloading in java and C#?

I know there is no such thing like Operator Overloading in Java and C#. A task is given to me by my teacher to achieve operator overloading in any of these languages. I don't know the deep concepts of these languages, only basic OOP. So can any one tell is there any other way to achieve this?
There is a thing called operator overloading in C#, check out this code snippet from MSDN:
public struct Complex
{
public int real;
public int imaginary;
public Complex(int real, int imaginary)
{
this.real = real;
this.imaginary = imaginary;
}
// Declare which operator to overload (+), the types
// that can be added (two Complex objects), and the
// return type (Complex):
public static Complex operator +(Complex c1, Complex c2)
{
return new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
}
}
Full list of overloadable operators
As des has shown, C# does have operator overloading. Java, on the other hand, does not. The way Java compares that two objects are equal is done through overriding the method equals(Object), which is inherited from the base object java.lang.Object. Here's an example usage:
public class MyClass {
private int value;
#Override
public boolean equals(Object o) {
return o instanceof MyClass && ((MyClass)o).value == this.value;
}
}
Of course this is only a workaround for replicating overloading the == operator. For other operators, such as >= or <= there is nothing. However, you can use OO to sort of recreate it by using a common interface:
interface Overloadable<T> {
public boolean isGreaterThan(T other);
public boolean isLessThan(T other);
}
public class MyClass implements Overloadable<MyClass> {
private int value;
#Override
public boolean equals(Object o) {
return o instanceof MyClass && ((MyClass)o).value == this.value;
}
#Override
public boolean isGreaterThan(MyClass other) {
return this.value > other.value;
}
#Override
public boolean isLessThan(MyClass other) {
return this.value < other.value;
}
}
This is by no means real operator overloading because, well, you're not overloading the operators. It does however provide the ability to compare objects in the same way.

Why code inside Generic functions ignores overloaded == operator

What is the workaround to this problem?
class Program
{
static void Main(string[] args)
{
var a = new Test();
var b = new Test();
var eq = Check(a, b);
}
private static bool Check<T>(T a, T b) where T : class
{
return a == b; //will not call overloaded ==
}
}
public class Test
{
public override bool Equals(object obj)
{
Test other = obj as Test;
if (ReferenceEquals(other, null)) return false;
return true;
}
public static bool operator ==(Test left, Test right)
{
return Equals(left, right);
}
public static bool operator !=(Test left, Test right)
{
return !(left == right);
}
}
The == operator is not used because your generic method exists independently of the types you will use for T. It has no way of knowing that all types used as T will overload the == operator... You can use the Equals method instead:
private static bool Check<T>(T a, T b) where T : class
{
return Equals(a, b);
}
The 'solution' here is to call
private static bool Check<T>(T a, T b) where T : class
{
//return a == b; // will not call overloaded ==
return a.Equals(b); // will cal overloaded Equals
}
It's a known behavior. MSDN says:
When applying the where T : class constraint, it is recommended that
you do not use the == and != operators on the type parameter because
these operators will test for reference identity only, not for value equality. This is the case even if these operators are overloaded in
a type used as an argument.
To check equality you have to implement IEqualityComparer (or directly call one of the Equal methods).
The workaround is to call the virtual Equals method, and override that:
private static bool Check<T>(T a, T b) where T : class
{
return a.Equals(b);
}
The overloaded == operator is resolved at compile time, so it is resolved to the System.Object implementation of the operator. A virtual method call is dispatched at run time, so the override of System.Object.Equals (if any) will get called.
In your code, the virtual Equals call is occurring in the overloaded == method, which is not called; that's why the Equals override is not called.
Another solution, if you have control of the classes being passed to the method, would be to constrain to IEquatable<T>, and implement that in your classes:
private static bool Check<T>(T a, T b) where T : class, IEquatable<T>
{
return a.Equals(b);
}
That will cause the overload to resolve to the Equals(T) method, which will save some type checking at run time.

Categories

Resources