繁体   English   中英

运算符在实现接口的类上重载

[英]Operator overloading on class that implements interface

假设我有一个接口IFoo和一个实现IFoo的类Foo。 我想定义自己的逻辑,根据它们包含的数据确定2个Foo实例是否相等,并重载==和!=运算符,以便在使用Foo时易于使用。

如果我有2个Foo实例,都存储为Foo,则可以正常工作。 但是,如果我有两个实例都存储为IFoo,则突然不再调用我的重载运算符。 此外,由于我无法在IFoo接口上定义运算符,并且Foo运算符重载中的至少一个参数必须为Foo类型,因此我看不到有任何方法可以成功使我的类型重载该运算符。 这个对吗?

另外,任何人都可以弄清为什么会这样吗? 通常,我希望将我的Foos存储为IFoos与确定调用哪个相等函数无关,因为从根本上说,它们仍然是Foos!

任何帮助真的很感激

谢谢

编辑:好的,因为我的意思似乎有些混乱,所以这里有一个例子,希望可以澄清一下:

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

运算符重载仅在编译时存在,编译后仅是对具有已知名称的特定静态方法的调用。

C#编译器可以识别Foo运算符重载,并用Foo.op_Equality(a,b)替换a == b 这意味着编译后,类Foo中存在非虚拟静态方法op_Equality 因此,不可能重载接口的运算符-接口不能具有静态方法。 而且,运算符方法是非虚拟的 ,这意味着实际方法是从变量类型而不是值的类型解析的,因此编译器将基于ab变量类型寻找可能的运算符重载,如果它们都是IFoo ,则它将只能在IFoo类型中查找op_Equality不能拥有它。

您只能为基于值类型解析的方法提供自定义逻辑-这些是虚拟方法,例如,您可以为Foo类型覆盖Equals方法,但是如果使用IFoo a == IFoo b无济于事。解析为Object.ReferenceEquals(a,b)

基本上是Aloraman所说的,但是让我用另一种方式看一下它是否变得更加清晰。

当您有两个声明为IFoo的变量,但是将它们实例化为Foo对象时,变量声明定义了语法检查中可用的变量。 变量声明在那里供编译器查看,但是实例化直到执行才发生,实例化就不会出现,因此编译器无法看到它们实际上是两个Foo对象。 因为IFoo没有并且不能有重载的运算符==,所以编译器正确地将其视为错误。

当编译器试图弄清楚用于某种操作的内容时,它不能知道那些对象实际上是Foo,因为分配这些IFoo变量以包含Foo对象是在执行期间发生的。 当您比较这两个IFoo变量时,编译器无法理解您的真正意图是使用实现IFoo和重载==的一个类。

但是,当将变量定义为Foo时,编译器就完全知道,在执行时,实例化它们时,必须将它们实例化为Foo类型,并且它确切地知道在哪里编译==运算符。

基本上,编译器在尝试编译==运算符时,不会遍历所有其他代码来查看如何实例化这两个操作数。 如果将它们定义为IFoo,则它将是仅有的信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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