【发布时间】:2011-09-30 01:01:42
【问题描述】:
谁能解释一下为什么C#接口不允许包含操作符?
谢谢。
【问题讨论】:
标签: c# interface operators static-methods
谁能解释一下为什么C#接口不允许包含操作符?
谢谢。
【问题讨论】:
标签: c# interface operators static-methods
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# 接口不能包含转换、相等或不等运算符
【讨论】:
您不能在接口上定义运算符,因为一个类可以实现多个接口。想象一下,如果这个代码是可能的:
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 == 运算符的作者假定,在进行比较时,对象的唯一重要方面是接口所包含的方面。有时这可能是正确的,但通常情况并非如此。
这就是为什么只在密封类上使用运算符是谨慎的。只有这样,您才能确定您的操作员对对象有足够的了解才能正常工作。
【讨论】:
如果您的方法无法在接口上正确实现,您可以调用将被派生类覆盖的 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;
}
}
【讨论】: