C# 接口不能包含运算符

发布于 2024-11-19 05:00:20 字数 43 浏览 1 评论 0原文

谁能解释一下为什么 C# 接口不允许包含运算符?

谢谢。

Can anyone please explain why C# interfaces are not allowed to contain operators?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧人哭 2024-11-26 05:00:20

C# 运算符必须是静态的。根据定义,接口适用于实例。没有机制要求类型来实现静态成员。

编辑:
从 C# 8.0 开始,如您所见 这里,现在可以在接口中定义本地方法并在接口本身中实现它们,例如,允许创建方法重载,而不需要实现也关心这些​​重载,当它们可能只提供附加参数时到必须实现的重载。
除此之外,您还可以在接口中定义运算符,尽管它们必须是静态的,因此它们必须在接口中实现。

因此,在 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);
    }
}

Edit 2020-01-23

您不能向接口添加转换、相等或不等运算符,否则您会遇到出现以下错误:

CS0567 C# 接口不能包含转换、相等或不等运算符

C# operators have to be static. Interfaces, by definition, apply to instances. There is no mechanism to require a type to implement static members.

EDIT:
Since C# 8.0, as you can see here, it is now possible to define local methods in interfaces and implement them within the interface itself, e.g. allowing to create method overloads without requiring implementations to care about those overloads as well, when they might just supply an additional parameter to the overload that has to be implemented.
Along with this, you can also define operators within interfaces, though they must be static and so they must be implemented in the interface.

So in C# 8.0 this will print "this works in C# 8" followed by "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);
    }
}

Edit 2020-01-23

You cannot add conversion, equality or inequality operators to interfaces, otherwise you'll hit the following error:

CS0567 C# Interfaces cannot contain conversion, equality, or inequality operators

鹿港巷口少年归 2024-11-26 05:00:20

您不能在接口上定义运算符,因为一个类可以实现多个接口。想象一下,如果这段代码是可能的:

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 来自另一个 DLL)。

即使你能以某种方式解决这种歧义,我们也应该问自己这是否是一个好主意。我希望上面的内容表明使用运算符==这是一个非常糟糕的主意。每个接口 == 运算符的作者假设,在进行比较时,对象唯一重要的方面是接口所包含的方面。有时这可能是真的,但通常并非如此。

这就是为什么谨慎的做法是仅在密封类上使用运算符。只有这样,您才能确保操作员对物体有足够的了解,以便正确工作。

You can't define operators on interfaces because a class can implement multiple interfaces. Imagine if this code were possible:

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 { ... }

Which == implementation should prevail if used on instances of Foobar? (And before you answer, imagine if IFoo/Fooness come from one DLL and IBar/Barness comes from another).

Even if you could somehow resolve that ambiguity, we should ask ourselves whether it would even be a good idea. I hope the above shows that with operator== it's a seriously bad idea. The author of the per-interface == operator presumes that the only important aspects of an object when it comes to comparison are those encompassed by the interface. Sometimes that can be true, but it's not generally true.

That's why it's prudent to only use operators on sealed classes. Only then can you be sure that your operator knows enough about the object to work correctly.

时间海 2024-11-26 05:00:20

如果您的方法无法在接口上正确实现,您可以调用将被派生类重写的 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;
        }
}

If your method could not be properly implemented on the interface, you can make a call to a self method that will be overriden by the derived class:

public interface INotification
{
        INotification Combine(INotification b);
        
        public static INotification operator +(INotification a, INotification b)
        {
            return a.Combine(b);
        }
}

Derived class:

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;
        }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文