C#接口不能包含操作符
Posted
技术标签:
【中文标题】C#接口不能包含操作符【英文标题】:C# interface cannot contain operators 【发布时间】:2011-09-30 01:01:42 【问题描述】:谁能解释一下为什么C#接口不允许包含操作符?
谢谢。
【问题讨论】:
【参考方案1】:C#operators have to be static。根据定义,接口适用于实例。没有要求类型实现静态成员的机制。
编辑: 从 C# 8.0 开始,如您所见 here,现在可以在接口中定义本地方法并在接口本身内实现它们,例如允许创建方法重载,而无需实现也关心这些重载,因为它们可能只是为必须实现的重载提供附加参数。 除此之外,您还可以在接口中定义运算符,但它们必须是静态的,因此必须在接口中实现。
所以在 C# 8.0 中,这将打印“this works in C# 8”后跟“1”:
interface ICanAdd
int Value get;
public static int operator+ (ICanAdd lvalue, int rvalue)
Console.WriteLine("this works in C# 8");
return lvalue.Value + rvalue;
class Add : ICanAdd
public int Value => 0;
class Program
static void Main(string[] args)
ICanAdd foo = new Add();
var x = foo + 1;
Console.WriteLine(x);
编辑 2020-01-23
您不能在接口中添加转换、相等或不等运算符,否则您会遇到以下错误:
CS0567 C# 接口不能包含转换、相等或不等运算符
【讨论】:
@pickles - 语言/编译器无法创建这样的构造并没有硬性原因(我认为实际上可能有一些可以做到 - 德尔福也许,它可以在 C++ 中使用模板(T::Method()))在某种程度上被模仿(至少是静态虚拟方法) - C# 选择不这样做。 这篇文章的第二个答案有一些关于为什么 C# 没有这个的评论。 ***.com/questions/259026/… 抱歉恢复一个旧线程,但由于索引括号运算符/“属性”不是静态的,它们可以在界面中使用。 @GregKramida C# 中的不同之处在于,索引器在技术上并不是 C++ 中的运算符。它是语言中的语法糖,它可以归结为 IL 中的实例方法 get_Item。在语法规范中,索引器和运算符分别声明且不同。 msdn.microsoft.com/en-us/library/aa664812(v=vs.71).aspx 感谢@DavideCannizzo 指出这在 C# 8 中发生了变化【参考方案2】:您不能在接口上定义运算符,因为一个类可以实现多个接口。想象一下,如果这个代码是可能的:
static class Fooness
public static operator==(IFoo l, IFoo r) ...
static class Barness
public static operator==(IBar l, IBar r) ...
public class Foobar : IFoo, IBar ...
如果在 Foobar 的实例上使用,哪个 == 实现应该占上风? (在你回答之前,想象一下如果 IFoo/Fooness 来自一个 DLL 而 IBar/Barness 来自另一个)。
即使你能以某种方式解决这种模棱两可的问题,我们也应该问问自己这是否是一个好主意。我希望以上内容表明使用 operator== 这是一个非常糟糕的主意。 per-interface == 运算符的作者假定,在进行比较时,对象的唯一重要方面是接口所包含的方面。有时这可能是正确的,但通常情况并非如此。
这就是为什么只在密封类上使用运算符是谨慎的。只有这样,您才能确定您的操作员对对象有足够的了解才能正常工作。
【讨论】:
【参考方案3】:如果您的方法无法在接口上正确实现,您可以调用将被派生类覆盖的 self 方法:
public interface INotification
INotification Combine(INotification b);
public static INotification operator +(INotification a, INotification b)
return a.Combine(b);
派生类:
public class Notification : INotification
public INotification Combine(INotification b)
_events.AddRange(b.Events);
_logs.AddRange(b.Logs);
ValidationResult.Errors.AddRange(b.GetValidationErrors());
return this;
public static Notification operator +(Notification a, Notification b)
a._events.AddRange(b.Events);
a._logs.AddRange(b.Logs);
a.ValidationResult += b.ValidationResult;
return a;
【讨论】:
以上是关于C#接口不能包含操作符的主要内容,如果未能解决你的问题,请参考以下文章