为什么.net的最佳实践是将自定义属性设计为密封的

本文关键字:自定义属性 密封 net 最佳 为什么 | 更新日期: 2023-09-27 18:12:23

我正在阅读Andrew Troelsen的Pro c# 2010和。net 4平台

在第十五章关于属性存在一个注释:

注意:出于安全考虑,将所有自定义属性设计为密封是. net的最佳实践。

作者没有解释为什么,有人能解释为什么吗?

为什么.net的最佳实践是将自定义属性设计为密封的

CA1813:避免未密封的属性:.NET框架类库提供了检索的方法自定义属性。默认情况下,这些方法搜索属性继承层次结构;属性。GetCustomAttribute搜索指定的属性类型,或任何属性类型扩展指定的属性类型。密封属性消除该搜索通过继承层次结构,并可以改进性能。

裁判:https://learn.microsoft.com/visualstudio/code-quality/ca1813-avoid-unsealed-attributes

属性只是运行时发现的元数据。正如引用的那样,如果其他人从您的自定义属性类派生,默认情况下。net也会发现他们,如果派生的属性类以您从未想过的方式修改原始属性的行为,这可能意味着安全风险。

尽管性能是密封属性类的主要原因,这里还是有一篇令人敬畏的文章来讨论它的安全方面。

密封属性还有一个原因。

考虑以下属性:

[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false)]
public class Attr1 : Attribute
{
}

这里只允许单个属性装饰:AllowMultiple = false

编译器不允许:

[Attr1]
[Attr1]
public class Foo
{
}

在后面的代码中,你可以安全地调用memberInfo.GetCustomAttribute(),如果找到多个给定类型的属性,它将抛出AmbiguousMatchException

现在让我们来继承:

public class Attr2 : Attr1
{
}

现在编译器是静默的。

[Attr1]
[Attr2]
public class Foo
{
}

因此,如果以后有人继承了你的属性并将带有两个属性的实体传递给你的代码,将会抛出意外异常。

完整的示例:

class Program
{
    static void Main(params string[] args)
    {
        typeof(Foo).GetCustomAttribute<Attr1>();
    }
    [AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public class Attr1 : Attribute
    {
    }
    public class Attr2 : Attr1
    {
    }
    [Attr1]
    [Attr2]
    public class Foo
    {
    }
    [Attr1]
    public class Bar : Foo
    {
    }
}

框架设计指南:可重用。net库的约定、习惯用法和模式只是说:

如果可能的话,

DO封装自定义属性类。这使得查找属性的速度更快。

我在那部分没有看到任何关于安全的内容,但是@Teoman Soygul说得很好。所以我同意Troelsen先生的观点。