【问题标题】:How can an Attribute enforce inheritance?属性如何强制继承?
【发布时间】:2025-11-28 01:00:02
【问题描述】:

为了用AttributeUsage装饰一个类,被装饰的类也必须继承自Attribute

我可以使用自定义属性强制执行类似的约束吗?

【问题讨论】:

    标签: c# inheritance attributes constraints


    【解决方案1】:

    AttributeUsageAttribute 显然是该语言的核心功能,因此C# specification 强制执行此限制:

    AttributeUsage 属性修饰的类必须直接或间接派生自System.Attribute。否则,会发生编译时错误。

    这意味着没有直接的方法可以实现这种限制。您可以编写自定义静态分析器以在错误使用时发出警告,或查看 Anton Anpilogov 的答案以了解解决方法。

    【讨论】:

    • 我认为这是魔法Contract.Requires(type.IsSubclassOf(typeof(Attribute))
    【解决方案2】:

    这样做的唯一方法是使用受保护的属性,但在这种情况下,您将强制您的属性的用户从您的属性类继承。

    abstract class CustomAttribute : Attribute {
        [AttributeUsage(AttributeTargets.Class)]
        protected sealed class MyTestAttribute : Attribute {}
    }
    
    [MyTest]
    class DerivedFromYourCustomAttribute : CustomAttribute {
    }
    
    [MyTest]
    class NotDerivedFromYourCustomAttribute {
    }
    

    【讨论】:

    • 这是一个很好的解决方法,但 AttributeUsageAttribute 不是 System.Attribute 的嵌套类型,所以它留下了一个问题 - 该限制是如何执行的?
    • @V0ldek:这就是我最初想知道的;也许是评论装饰?然而,这确实实现了类似的效果。虽然MyTestAttribute 限制为protected,但无法找到用该属性修饰的类型。我公开了MyTestAttribute,这样我就可以找到装饰类。
    • @V0ldek:: AttributeUsageAttribute 接受 C# 编译器的特殊处理。你不可以做这个。你可以看到它的源代码here。没有明显的特征。只有一个有趣的细节:AttributeUsageAttribute 应用于自身!
    • 我在 AttributeUsageAttribute 的 cmets 中找不到任何东西来强制执行它
    • @IAbstract:这仅适用于InternalGetCustomAttributes 方法的参数,与AttributeUsageAttribute 类无关。