I have the following scenario:
public class SomeClass {
// Have some other data members as well
public int i ;
}
public class TestClass {
public bool SomeFunction() {
SomeClass a = new SomeClass();
SomeClass b = new SomeClass();
if (a == b) // this is where I am getting compile error
return true;
return false;
}
public static bool operator==(SomeClass a, SomeClass b) {
if (a.i == b.i)
return true;
// compare some other members as well
return false;
}
}
Is this possible to achieve in C#?
Thanks for the help!
No, it's not possible to override an operator from a class that is not involved in the operation.
You can make a class that implements IEualityComparer<SomeClass>, which can be used instead of the standard comparison in some cases, for example in a dictionary:
var x = new Dictionary<SomeClass, string>(new SomeClassEqualityComparer());
If you just want to use the comparison in your own class, you could make it a regular static method instead of overriding an operator:
public static bool SomeClassEqual(SomeClass a, SomeClass b) {
if (a.i == b.i) {
return true;
}
// compare some other members as well
return false;
}
Usage:
if (SomeClassEqual(a, b))
To begin with, you can't use return true; on a void method.
Second, overriding operators should be applied to the host class. In your case, inside SomeClass rather than inside TestClass.
Third, when you implement == overriding operator, you should also implement != .
Here is your code, revised and working:
public class SomeClass
{
// Have some other data members as well
public int i;
public static bool operator ==(SomeClass a, SomeClass b)
{
if (a.i == b.i)
return true;
// compare some other members as well
return false;
}
public static bool operator !=(SomeClass a, SomeClass b)
{
return !(a == b);
}
}
public class TestClass
{
public bool SomeFunction()
{
SomeClass a = new SomeClass();
SomeClass b = new SomeClass();
if (a == b) // this is where I am getting compile error
return true;
return false;
}
}
Related
We have GUIDs as identifiers in our systems. As it's easy to mess up and pass the id of one entity into a method that expects the id of another entity (lets say you pass the OrderId to the InvoiceId by mistake because it's all Guids) we created our own types for Guids, so the compiler can easily tell me "hey, don't pass an OrderId here, I expect an InvoiceId".
So basically, we have lots of wrappers around Guid. Those wrappers work well, they are basically copies of the Guid interface delegating all the work to their internally stored Guid.
One thing that I cannot figure out is that Assert.AreEqual(a, b) on two of our custom identifiers will fail. It calls object.Equals(a, b) that in turn calls a == b and that will not call my operator == but instead call something else and return false. It does not for Guid though and I cannot figure out what I missed.
What do I need to implement for my custom types to actually work and return true on object.Equals(a, b) given that it already does on operator ==?
namespace ConsoleApp13
{
using System;
using System.Runtime.InteropServices;
//// Same signature, interfaces and and attributes as
//// https://referencesource.microsoft.com/#mscorlib/system/guid.cs
[StructLayout(LayoutKind.Sequential)]
[Serializable]
[ComVisible(true)]
// not accessible for me: [System.Runtime.Versioning.NonVersionable]
public struct CustomId : IFormattable, IComparable, IComparable<CustomId>, IEquatable<CustomId>
{
public static readonly CustomId Empty = new CustomId();
private readonly Guid internalGuid;
private CustomId(Guid guid)
{
this.internalGuid = guid;
}
public static bool operator ==(CustomId a, CustomId b)
{
return a.internalGuid == b.internalGuid;
}
public static bool operator !=(CustomId a, CustomId b)
{
return !(a.internalGuid == b.internalGuid);
}
public static CustomId NewGuid()
{
return new CustomId(Guid.NewGuid());
}
public static implicit operator Guid(CustomId value)
{
return value.internalGuid;
}
public static explicit operator CustomId(Guid value)
{
return new CustomId(value);
}
public override string ToString()
{
return "[" + this.GetType().Name + ":" + this.internalGuid.ToString("D") + "]";
}
public override int GetHashCode()
{
return this.internalGuid.GetHashCode();
}
public override bool Equals(object obj)
{
return this.internalGuid.Equals(obj);
}
public bool Equals(CustomId other)
{
return this.internalGuid.Equals(other.internalGuid);
}
public int CompareTo(object obj)
{
return this.internalGuid.CompareTo(obj);
}
public int CompareTo(CustomId other)
{
return this.internalGuid.CompareTo(other.internalGuid);
}
public string ToString(string format, IFormatProvider formatProvider)
{
return this.internalGuid.ToString(format, formatProvider);
}
}
internal static class Program
{
internal static void Main()
{
{
var a = CustomId.NewGuid();
var b = a;
// shows true false
Console.WriteLine("{0} {1}", a == b, object.Equals(a, b));
}
{
var a = Guid.NewGuid();
var b = a;
// shows true true
Console.WriteLine("{0} {1}", a == b, object.Equals(a, b));
}
Console.WriteLine(#"Done.");
Console.ReadLine();
}
}
}
Your code here:
public override bool Equals(object obj)
{
return this.internalGuid.Equals(obj);
}
is going to unwrap itself, but it doesn't unwrap the other instance, so : it will always fail if obj is a CustomId, as the Guid won't expect to be handed a CustomId (it wants a Guid). Perhaps this should be:
public bool Equals(object obj) => obj is CustomId cid && cid == this;
Note that CompareTo should probably be similar:
public int CompareTo(object obj) => obj is CustomId cid ? this.CompareTo(cid) : -1;
The answer from Marc Gravell is correct but I want to note something.
It calls object.Equals(a, b) that in turn calls a == b
This is a wrong assumption. object.Equals(a, b) will call a.Equals(b) if both of them are not null. Subtle difference but it is a difference:
https://referencesource.microsoft.com/#mscorlib/system/object.cs,d9262ceecc1719ab
public static bool Equals(Object objA, Object objB)
{
if (objA==objB) {
return true;
}
if (objA==null || objB==null) {
return false;
}
return objA.Equals(objB);
}
Is there anyway to make is so that I can say something like
if(boolClass) {}
Where the boolClass is calling a contained function. Kinda like an overloaded bool operator or something.
Thanks for any help.
There is actually a 'true' operator you can use for this purpose, though it's a bit obscure. This is slightly more specific than a conversion to bool, as it is limited to use in expressions that check for true/false.
public class BoolClass
{
public static bool operator true(BoolClass instance)
{
return true; //Logic goes here
}
public static bool operator false(BoolClass instance)
{
return true; //Logic goes here
}
public void Test()
{
BoolClass boolClass = new BoolClass();
if (boolClass)
{
//Do something here
}
}
}
Note that MS actually recommends against using this operator,as it was originally intended to allow for a kind of nullable bool type (where a value could be neither true nor false). Since nullable bools are now natively supported, those are preferred. I'd recommend against using it in production code, mainly because most developers won't be familiar with the syntax, causing confusion.
My first point would be to caution you against this, usually you want to use the bool or bool? classes available directly or indirectly.
If you are certain that is what you need, then you will need an implicit conversion operator to bool
//In the definition of boolClass
public static implicit operator bool(boolClass obj)
{
//Return a bool in this method
}
You can use a implicit operator to convert your class to a Boolean.
This is a full and simple example :
Classe
using System;
namespace TestLogic
{
internal class FuzzyLogic
{
public FuzzyLogic(Double init)
{
this.value = init;
}
public Double value { get; private set; }
public static implicit operator Boolean(FuzzyLogic logic)
{
return logic.value < 0.1;
}
}
}
Using the convertion
using System;
namespace TestLogic
{
internal class Program
{
private static void Main(string[] args)
{
FuzzyLogic logic = new FuzzyLogic(0.2);
if (logic)
{
Console.WriteLine("It's true !");
}
else
{
Console.WriteLine("It's not true !");
}
Console.ReadLine();
}
}
}
Sounds like a property:
public bool boolClass
{
get { return false; } // or a calculated boolean value
}
You can invoke it exactly like you asked about from inside the same class:
if(boolClass) {}
Add a conversion operator to your class. Example (ideone):
using System;
public class A
{
private int i;
public int I { get { return i; } }
public A(int i) { this.i = i; }
public static implicit operator bool(A a) { return a.i != 0; }
}
public class Test
{
public static void Main()
{
A a1 = new A(0);
if (a1)
Console.WriteLine("a1 is true");
else
Console.WriteLine("a1 is false");
A a2 = new A(42);
if (a2)
Console.WriteLine("a2 is true");
else
Console.WriteLine("a2 is false");
}
}
Output:
a1 is false
a2 is true
Which method of DynamicObject do I have to override in order to get a different behavior (in the dynamic class) based on the context in which the instance is used?
Here is an example of what I am trying to accomplish:
class DynamicTest : DynamicObject
{
public DynamicTest(string xyz)
{
_xyz = xyz;
}
private string _xyz;
//TODO: what do I need to implement to get required behaviour?
}
class Program
{
static void Main(string[] args)
{
dynamic foo = new DynamicTest("test);
if (foo) // treat foo as boolean
{ // jump in here when _xyz of foo has a value
System.Console.WriteLine(foo); //treat foo as string
}
else
{ // jump in here when _xyz of foo is null
System.Console.WriteLine("No Value In Object");
}
}
}
I don't know why are you trying to do this and I will definitely NOT will recommend doing this, but you can override TryConvert method on DynamicObject like:
class DynamicTest : DynamicObject
{
public DynamicTest(string xyz)
{
_xyz = xyz;
}
private string _xyz;
public override bool TryConvert(ConvertBinder binder, out Object result)
{
Console.WriteLine ("TryConvert was called");
Console.WriteLine ("Is explicit: "+binder.Explicit);
if(binder.Type == typeof(bool))
{
result = true;
return true;
}
else if(binder.Type == typeof(string))
{
result = _xyz;
return true;
}
result = null;
return false;
}
public override string ToString()
{
return _xyz;
}
}
Now there are some issues: ToString is required for Console.WriteLine, it doesn't try to convert if no implicit convertions exist (because WriteLine is overloaded), so it calls ToString. Implicit and explicit conversions to bool pass, but if you use foo inside if - you will get RuntimeBinderException: Cannot implicitly convert type 'DynamicTest' to 'bool'.
Examples:
dynamic foo = new DynamicTest("test:");
bool boolFoo = foo; //passes, TryConvert is called with `binder.Explicit` == false
bool boolFoo1 = (bool)foo; //passes, TryConvert is called with `binder.Explicit` == true
if(foo) //throws RuntimeBinderException
I think implicit operator can help you
Example code:
class DynamicTest : DynamicObject
{
public DynamicTest(string xyz)
{
_xyz = xyz;
}
private string _xyz;
public static implicit operator bool(DynamicTest rhs)
{
return rhs._xyz != null;
}
public static implicit operator string(DynamicTest rhs)
{
return rhs._xyz;
}
//TODO: what to override to get required behaviour
}
class Program
{
static void Main(string[] args)
{
dynamic foo = new DynamicTest("test");
if (foo) // treat foo as boolean
{ // jump in here when _xyz of foo has a value
System.Console.WriteLine((string)foo); //treat foo as string //Importat: (string)foo to go operatorstring
}
else
{ // jump in here when _xyz of foo is null
System.Console.WriteLine("No Value In Object");
}
}
}
I have hierarchy of classes:
class A{}
class B: A {}
class C:B {}
is it possible to implement method in class A and it would be inherited by derived classes B and C and so on and that method should return value of class type?
A val = A.method(); (val is A)
B val = B.method(); (val is B)
C val = C.method(); (val is C)
And I don't want use of generics in call of this method, ie:
C val = C.method<C>();
Guys, excuse me, one elaboration, this method should be static.
I don't want to use generic in method istelf, because it forces to point type that method should return, whereas method should return type of its class.
class A
{
Method<T>()
{
T result;
return result;
}
}
If I have such method I can change return type:
D result = A.Method<D>();
but I wanted it to return value of type A;
No, that is not possible.
To call the method like that it would have to be static, and static methods are not inherited.
Using B.method() to call a static method in A is the same as using A.method(). The compiler just uses the type to determine where the method is, but it's impossible for the method to know if it was called using the A or B type.
Use an extension method:
class Program
{
static void Main(string[] args)
{
B x = new B();
x.Method();
}
}
public static class Ext
{
public static T Method<T>(this T obj)
where T : A,new()
{
return new T();
}
}
public class A
{
}
public class B : A
{
}
Or a variation thereof. Note that you must have some public member capable of creating an instance of the specified type. To expound, the compiler 'guesses' the value of the type parameter. The method is still generic, but generic syntax is nowhere to be seen when the method is called (usually).
Using some design patterns from C++ makes this easier:
class A
{
protected virtual A method_impl() { return new A(); }
public A method() { return method_impl(); }
}
class B : A
{
protected override A method_impl() { return new B(); }
public new B method() { return (B)method_impl(); }
}
class C : B
{
protected override A method_impl() { return new C(); }
public new C method() { return (C)method_impl(); }
}
Of course, this exact problem never arises in C++, which allows covariant return types for overrides.
Another way, using IoC pattern:
class A
{
protected virtual void method_impl(A a) { a.initialize(); }
public A method() { A result = new A(); method_impl(result); return result; }
}
class B : A
{
public new B method() { B result = new B(); method_impl(result); return result; }
}
class C : B
{
public new C method() { C result = new C(); method_impl(result); return result; }
}
I'm building a hierarchical collection class that orders magnetic resonance images spatially and arranges them into groupings based on the various acquisition parameters that were used to generate them. The specific method used to perform the grouping is provided by the user of the class. I've abstracted out the relevant features in the sample code below. For the IEquatable<MyClass> implementation, I'd like to be able to compare the _myHelperDelegate attributes of two MyClass instances to determine if both delegates point to the same piece of code. The (_myHelperDelegate == other._myHelperDelegate) clause in the if statement below is clearly the wrong way to go about doing this (it fails to compile, giving the error "Method name expected"). My question is, is there a way to compare two delegates to determine if they reference the same piece of code? If so, how do you do that?
public class MyClass : IEquatable<MyClass>
{
public delegate object HelperDelegate(args);
protected internal HelperDelegate _myHelperDelegate;
public MyClass(HelperDelegate helper)
{
...
_myHelperDelegate = helper;
}
public bool Equals(MyClass other)
{
if (
(_myHelperDelegate == other._myHelperDelegate) &&
(... various other comparison criteria for equality of two class instances... )
)
return true;
return false;
}
}
The following compiles and works as expected.
private void Form1_Load(object sender, EventArgs e)
{
var helper1 = new TestDelegates.Form1.MyClass.HelperDelegate(Testing);
var helper2 = new TestDelegates.Form1.MyClass.HelperDelegate(Testing2);
var myClass1 = new MyClass(helper1);
var myClass2 = new MyClass(helper1);
System.Diagnostics.Debug.Print(myClass1.Equals(myClass2).ToString()); //true
myClass2 = new MyClass(helper2);
System.Diagnostics.Debug.Print(myClass1.Equals(myClass2).ToString()); //false
}
private object Testing()
{
return new object();
}
private object Testing2()
{
return new object();
}
public class MyClass : IEquatable<MyClass>
{
public delegate object HelperDelegate();
protected internal HelperDelegate _myHelperDelegate;
public MyClass(HelperDelegate helper)
{
_myHelperDelegate = helper;
}
public bool Equals(MyClass other)
{
if (_myHelperDelegate == other._myHelperDelegate)
{
return true;
}
return false;
}
}
Per msdn, Delegate.Equals method returns:
true if obj and the current delegate have the same targets, methods, and invocation list; otherwise, false.
Have you tried this?
Old question, but I wrote a simple example program to demonstrate comparing delegates with Delegate.Equals -
public delegate int test1(int t);
public static int asdf(int t)
{
return t + 5;
}
public static int asdf2(int x)
{
return x + 7;
}
public static void CompareDelegates(test1 test1, test1 test2)
{
Console.WriteLine(test1 == test2);
}
public static void Main(string[] args)
{
test1 test1 = asdf;
test1 test2 = asdf2;
test1 test3 = asdf;
CompareDelegates(test1, test1);
CompareDelegates(test1, test2);
CompareDelegates(test2, test3);
CompareDelegates(test1, test3);
}
// Outputs:
//
// True
// False
// False
// True