为什么.Net最佳实践将自定义属性设计为密封?
我正在阅读Pro C#2010和 Andrew Troelsen 的.Net 4平台 。
在第15章关于属性存在一个注释:
注意:出于安全原因,将所有自定义属性设计为密封被视为.Net最佳实践。
作者没有解释原因,有人可以解释原因吗?
CA1813:避免未密封的属性:.NET Framework类库提供了检索自定义属性的方法。 默认情况下,这些方法搜索属性inheritance层次结构; 例如,Attribute.GetCustomAttribute搜索指定的属性类型或扩展指定属性类型的任何属性类型。 密封属性消除了通过inheritance层次结构的搜索,并且可以提高性能。
参考: https : //docs.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
。
我们现在inheritance:
public class Attr2 : Attr1 { }
现在编译器是静默的。
[Attr1] [Attr2] public class Foo { }
因此,如果稍后某人从您的属性inheritance并传递回您的代码,则会抛出标记有两个属性意外exception的实体。
完整示例:
class Program { static void Main(params string[] args) { typeof(Foo).GetCustomAttribute(); } [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库的约定,惯用语和模式只是说:
如果可能,请密封自定义属性类。 这样可以更快地查找属性。
我在那个部分没有看到关于安全性的任何内容,但@Teoman Soygul提出了一个很好的观点。 所以我同意Troelsen先生的观点。