为什么.Net最佳实践将自定义属性设计为密封?

Aca*_*uza 30 .net c# attributes

我正在阅读Pro C#2010和 Andrew Troelsen 的.Net 4平台.

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

注意:出于安全原因,将所有自定义属性设计为密封被视为.Net最佳实践.

作者没有解释原因,有人可以解释原因吗?

Teo*_*gul 33

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

参考:https://docs.microsoft.com/visualstudio/code-quality/ca1813-avoid-unsealed-attributes

属性只是在运行时发现的元数据.正如引用的那样,如果其他人派生自您的自定义属性类,默认情况下.NET也会找到它们,如果派生属性类以某种方式修改原始属性的行为,这可能意味着存在安全风险至.

尽管性能是密封属性类的主要原因,但这是一篇涉及其安全方面强大文章.

  • @AcazSouza,那是不同的。`inherit` 参数控制是否应该搜索您正在查询的元素的祖先。也就是说,是否也应该检查基本类型。但是,它并不限制派生属性类型是否包含在结果中。 (3认同)

Pav*_*nin 7

封印属性还有一个原因。

考虑以下属性:

[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false)]
public class Attr1 : Attribute
{
}
Run Code Online (Sandbox Code Playgroud)

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

编译器不允许这样做:

[Attr1]
[Attr1]
public class Foo
{
}
Run Code Online (Sandbox Code Playgroud)

稍后在代码中,您可以安全地调用,如果找到给定类型的多个属性,memberInfo.GetCustomAttribute()则会抛出异常。AmbiguousMatchException

现在让我们继承:

public class Attr2 : Attr1
{
}
Run Code Online (Sandbox Code Playgroud)

现在编译器沉默了。

[Attr1]
[Attr2]
public class Foo
{
}
Run Code Online (Sandbox Code Playgroud)

因此,如果稍后有人继承您的属性并将其传递回您的代码,则某些标记有这两个属性的实体将引发意外异常。

完整示例:

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
    {
    }
}
Run Code Online (Sandbox Code Playgroud)