确保编译时接口互斥?

发布于 2024-11-06 14:53:36 字数 484 浏览 7 评论 0原文

我想确保在编译时在同一个类上永远不会找到两个接口,类似于 AttributeUsage 在编译时检查自定义属性。

例如:

[InterfaceUsage(MutuallyExclusive = typeof(B))]
interface A {
    //...
}

interface B {
    //...
}

class C : A, B { //should throw an error on compile time
    //...
}

我显然可以在运行时通过反射来做到这一点,但我对编译时解决方案感兴趣。

我想这个可能不存在现成的 - 但有没有一种方法可以创建一个在编译时运行的自定义属性,就像 AttributeUsage 一样?

I'd like to ensure that two interfaces are never found on the same class at compile-time, similar to how AttributeUsage checks custom Attributes at compile-time.

e.g.:

[InterfaceUsage(MutuallyExclusive = typeof(B))]
interface A {
    //...
}

interface B {
    //...
}

class C : A, B { //should throw an error on compile time
    //...
}

I can obviously do this at runtime with reflection, but I'm interested in a compile-time solution.

I'd imagine that one probably doesn't exist out of the box - but is there a way to create a custom attribute that is run at compile-time, much like AttributeUsage is?

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

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

发布评论

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

评论(4

最后的乘客 2024-11-13 14:53:36

另一种方法是将它们更改为抽象类。

A different approach could be to change them to Abstract classes.

迟到的我 2024-11-13 14:53:36

给他们两个具有相同签名但返回类型不兼容的方法怎么样?

How about giving them two methods with identical signatures, but incompatible return types?

楠木可依 2024-11-13 14:53:36

一个“解决方法”是在两个接口中添加 /// ,警告由于这样那样的原因,它们不应该一起使用。它用警告信号解决了一个陷阱,但总比没有好。

我遇到了类似的情况:本地和全球条件。一个只能依赖于数组中某个位置周围的固定部分,而另一个则根本不能依赖于位置。把两者放在一起,你就得到了一个无用的条件。

A "workaround" would be to just add /// to both interfaces warning that they shouldn't be used together, because of such and such reason. It's addressing a pitfall with a caution sign, but it's better than nothing.

I ran into a similar case: Local and Global conditions. One can only depend on a fixed portion of the array around a position, while the other cannot depend on position at all. Put both together and you have a useless condition.

南城追梦 2024-11-13 14:53:36

这可能不是 100% 的方式,但对于您想要互斥的接口,您可能会在编译时获得一些错误。假设我们想禁止人们在同一个类上实现 catdog 接口:

interface cat_or_dog
{
    bool IsCute { get; }
}

interface cat_or_dog<A> : cat_or_dog where A : cat_or_dog
{
    A Self { get; }
}

interface cat : cat_or_dog<cat>
{
    Guid Meow { get; }
};

interface dog : cat_or_dog<dog>
{
    Single Woof { get; }
};

通过这种设置,如果一个类实现了,你实际上会得到一个致命的编译错误尝试公开实现两个互斥的接口,如 demo3demo4 中所示。这是由共享基类 cat_or_dog 中成员的返回值的 Type 冲突引起的:(

class demo1 : cat         // ok
{
    public bool IsCute => true;
    public cat Self => this;
    public Guid Meow => Guid.NewGuid();
};

class demo2 : dog         // ok
{
    public bool IsCute => true;
    public dog Self => this;
    public Single Woof => 10.0f;
};

class demo3 : cat, dog // CS0535: "doesn't implement 'dog.Woof' and 'cat_or_dog<dog>.Self'
{
    public bool IsCute => default;
    public cat Self => this;
    public Guid Meow => Guid.NewGuid();
};

class demo4 : dog, cat // CS0535: "doesn't implement 'cat.Meow' and 'cat_or_dog<cat>.Self'
{
    public bool IsCute => default;
    public dog Self => this;
    public Single Woof => 10.0f;
};

Meow 和 < code>Woof 错误是由于 IDE 的自动接口实现功能在更严重的错误之后由于某种原因未完成重构而导致的)

在此处输入图像描述

然而,正如您所知,这是一个奇怪的重复模板模式的变体,因此仍然有可能“错误地”实现这两个接口通过使用 C# 显式接口实现:

class demo5 : dog, cat         // ok
{
    public bool IsCute => true;

    cat cat_or_dog<cat>.Self => this;
    Guid cat.Meow => throw null;

    dog cat_or_dog<dog>.Self => this;
    float dog.Woof => 10.0f;
};

This may not be 100% of the way there, but you can obtain some errors at compile-time for interfaces that you want to be mutually-exclusive. Assuming we want to disallow people from implementing both of the interfaces cat and dog on the same class:

interface cat_or_dog
{
    bool IsCute { get; }
}

interface cat_or_dog<A> : cat_or_dog where A : cat_or_dog
{
    A Self { get; }
}

interface cat : cat_or_dog<cat>
{
    Guid Meow { get; }
};

interface dog : cat_or_dog<dog>
{
    Single Woof { get; }
};

With this setup, you will get actually get a fatal compile error if a class tries to implement both of the mutually exclusive interfaces publically, as shown in demo3 and demo4. It's caused by a Type collision on the return-value of a member in the shared base class cat_or_dog<A>:

class demo1 : cat         // ok
{
    public bool IsCute => true;
    public cat Self => this;
    public Guid Meow => Guid.NewGuid();
};

class demo2 : dog         // ok
{
    public bool IsCute => true;
    public dog Self => this;
    public Single Woof => 10.0f;
};

class demo3 : cat, dog // CS0535: "doesn't implement 'dog.Woof' and 'cat_or_dog<dog>.Self'
{
    public bool IsCute => default;
    public cat Self => this;
    public Guid Meow => Guid.NewGuid();
};

class demo4 : dog, cat // CS0535: "doesn't implement 'cat.Meow' and 'cat_or_dog<cat>.Self'
{
    public bool IsCute => default;
    public dog Self => this;
    public Single Woof => 10.0f;
};

(The Meow and Woof errors are caused when the automatic interface implementation feature of the IDE not completing the refactoring after the more serious error, for some reason)

enter image description here

As you surely know however, this is a variation of the curiously recurring template pattern, so it is still possible to "incorrectly" implement both interfaces by using C# explicit interface implementation:

class demo5 : dog, cat         // ok
{
    public bool IsCute => true;

    cat cat_or_dog<cat>.Self => this;
    Guid cat.Meow => throw null;

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