C#:如何实现和使用NotNull和CanBeNull属性
我想让程序员和我自己知道一个方法不需要null
,如果你真的发送null
,结果将不会很漂亮。
在Lokad.Quality
命名空间中的Lokad共享库中有一个NotNullAttribute
和一个CanBeNullAttribute
。
但是,这是如何工作的? 我查看了这两个属性的源代码,看起来像这样:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] [NoCodeCoverage] public sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] [NoCodeCoverage] public sealed class CanBeNullAttribute : Attribute { }
两个从Attribute
inheritance的空类。 他们如何使用? 你必须查找XML文档,并知道它在那里? 因为我试图使我自己的属性的副本,并使用Lokad版本,但是当我试图直接发送null,我没有消息。 无论是从ReSharper还是从VS. 这实际上是我所期望的 但他们是如何使用的? 我可以以某种方式让VS为我生成警告,如果我尝试发送那里是空的东西吗? 还是只是在某种testing框架中使用? 要么?
从中期来看,“代码合同”(4.0版)将会是更好的答案。 他们现在( 学术或商业许可证),但将更多地集成在VS2010中。 这可以提供静态分析和运行时支持。
(编辑)例子:
Contract.RequiresAlways( x != null );
这么简单…代码契约引擎在IL级别工作,所以它可以在构build期间或运行时分析调用代码中的警告/错误。 为了向后兼容,如果您有现有的validation代码,您可以告诉它完整性检查结束的位置,剩下的工作就完成了:
if ( x == null ) throw new ArgumentNullException("x"); Contract.EndContractBlock();
这可以通过AOP来完成,通过这个通知,运行时通知会validation方法参数是否为空,以及是否允许空值。 有关AOP,请参阅PostSharp和Spring.NET 。
至于ReSharper,请参阅Annotated Framework :
我们已经分析了很多.NET Framework类库和NUnit框架,并且通过使用JetBrains.Annotations命名空间中的一组自定义属性,通过外部XML文件对其进行了注释,特别是:
- StringFormatMethodAttribute(用于将格式string作为参数的方法)
- InvokerParameterNameAttribute(对于具有应该与调用者参数之一匹配的string文字参数的方法)
- AssertionMethodAttribute(用于断言方法)
- AssertionConditionAttribute(用于断言方法的条件参数)
- TerminatesProgramAttribute(用于终止控制stream的方法)
- CanBeNullAttribute(对于可以为null的值)
- NotNullAttribute(对于不能为null的值)
这些注释用于ReSharper,并从JetBrains.Annotations命名空间复制。 一个框架可以把它们放在他们自己的名字空间中,但是,ReSharper不会自动select这些注释 – 你需要告诉ReSharper在选项对话框中使用自定义名称空间。 一旦你select了新的命名空间,ReSharper的分析将会提取这些属性并给你提供亮点和警告。
正如Anton Gogolev指出的那样,可以使用PostSharp创build属性(注意,CodeContract在方法体内使用静态方法调用)
2013年2月更新:PostSharp 3.0新版本(目前处于testing阶段)将支持validation参数,字段和属性
1)文章validate-parameters-using-attributes已经实现了
公共类NotEmpty:ParameterAttribute
公共类NotNull:ParameterAttribute
[AttributeUsage(AttributeTargets.Parameter)]
公共抽象类ParameterAttribute:Attribute
{
public abstract void CheckParameter(ParameterInfo parameter, object value);
}
它还需要具有方法边界方面的方法属性来处理参数属性。
2)在文章的评论中,有非常类似于 NonNull / NonEmpty的实现的链接
[return:NonNull] public SomeObject SomeMethod([NonNull] AnotherObject param1)
源代码位于谷歌代码Torch / DesignByContract
3)另一个更复杂的例子在http://badecho.com/2011/11/validating-method-parameters-with-postsharp/