简体   繁体   中英

Operator overloading on class that implements interface

Suppose I have an interface IFoo, and a class Foo that implements IFoo. I want to define my own logic for determining if 2 instances of Foo are equal based on the data they contain and overload the == & != operators for ease of use when working with Foo.

If I have 2 instances of Foo, both stored as Foo, then this works fine. However, if I have 2 instances both stored as IFoo, suddenly my overloaded operators aren't being called anymore. Furthermore, since I can't define an operator on my IFoo interface and at least one of the arguments in my Foo operator overload must be of type Foo, I can't see that there's any way I can successfully overload the operator on my type. Is this correct?

Also, can anyone clear up why this is happening? Normally I'd expect that the fact my Foos are being stored as IFoos should be irrelevant in determining which equality function gets called, since fundamentally they're still Foos!

Any help really appreciated

Thanks

Edit: Ok, since there seems to be a bit of confusion of what I mean, here's an example which should hopefully clarify a bit:

public interface IFoo
{
}

public class Foo : IFoo
{
    public static bool operator==(Foo left, Foo right)
    {
        ....
    }
}

Foo foo1 = new Foo();
Foo foo2 = new Foo();
bool comparison1 = foo1 == foo2    //This is successfully calling the overloaded operator

IFoo ifoo1 = foo1;
IFoo ifoo2 = foo2;
bool comparison2 = ifoo1 == ifoo2    //This isn't

Operator overloading exists in compile-time only, after compilation it is just a call to a specific static method with well-known name.

C# compiler recognizes operator overloading for Foo and replaces a == b with Foo.op_Equality(a,b) . That means there is non-virtual static method op_Equality in class Foo after compilation. Therefore it is not possible to overload operators for interfaces - interfaces cannot have static methods. Moreover, operator methods are non virtual , that means actual method is resolved from types of variables, not types of values, so compiler will look for possible operator overloading based on variable types of a and b , if both of them are IFoo , then it can only look for op_Equality in IFoo type - which cannot have it.

You can provide custom logic only for methods which are resolved based on types of values - those are virtual methods, eg you can override Equals method for Foo type, but it won't help you with IFoo a == IFoo b , which will be resolved to Object.ReferenceEquals(a,b)

Basically what Aloraman said, but let me put it another way to see if it gets clearer.

When you have two variables declared as IFoo, but then you instantiate them as Foo objects, the variable declaration defines what is available at the syntax check. The variable declaration is there for the compiler to see, but the instantiation, which does not occur until execution, is not, so the compiler has no way to see that those are really two Foo objects. Because IFoo does not have, and cannot have an overloaded operator ==, the compiler rightly sees that as an error.

When the compiler tries to figure out what to use for some operation, it cannot know that those objects are really Foo, because assigning those IFoo variables to contain Foo objects happens during execution. The compiler cannot read your mind that you really mean to use the one class that implements IFoo and overloads == when you compare those twoo IFoo variables.

But when the variables are defined as Foo, the compiler knows perfectly well that at execution, when they get instantiated, they will have to be instantiated as Foo type, and it knows exactly where to go to compile that == operator.

Basically, the compiler, when it tries to compile that == operator, does NOT go over all your other code to see how you instantiated the two operands. If they are defined as IFoo, that is the only information it can have.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM