C#:如何实现和使用NotNull和CanBeNull属性

时间:2009-04-27 07:35:59

标签: c# attributes null

我想让程序员和我自己知道方法不需要null,如果你确实发送null,结果也不会很好。

NotNullAttribute命名空间中的Lokad Shared Libraries中有CanBeNullAttributeLokad.Quality

但这怎么办?我查看了这两个属性的源代码,它看起来像这样:

[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继承的两个空类。它们是如何使用的?你需要查找xml文档并知道它在那里吗?因为我试图制作我自己的属性副本并使用Lokad版本,但是当我尝试直接发送null时,我没有收到任何消息。既不是来自ReSharper也不是来自VS.实际上我有点期待。但他们是如何使用的呢?如果我尝试发送一些空的东西,我可以以某种方式让VS为我生成警告吗?或者它只是在某种测试框架中使用?或?

4 个答案:

答案 0 :(得分:46)

在中期,“代码合同”(4.0版)将是一个更好的答案。它们现在可用(具有academiccommercial许可证),但将更多地集成在VS2010中。这可以提供静态分析和运行时支持。

(编辑)示例:

Contract.RequiresAlways( x != null );

简单......代码契约引擎在IL级别工作,因此它可以分析并在构建期间或运行时从调用代码中抛出警告/错误。为了向后兼容,如果您有现有的验证代码,您可以告诉它完整性检查的结束位置,它将完成剩下的工作:

if ( x == null ) throw new ArgumentNullException("x");
Contract.EndContractBlock();

答案 1 :(得分:19)

这可以使用AOP来完成,其中Advice在运行时验证方法参数是否为null以及是否允许空值。有关AOP,请参阅PostSharpSpring.NET

至于ReSharper,请参阅Annotated Framework

  

我们分析了.NET Framework类库以及NUnit Framework的很大一部分,并使用JetBrains.Annotations命名空间中的一组自定义属性,通过外部XML文件对其进行了注释,具体为:

     
      
  • StringFormatMethodAttribute(对于将格式字符串作为参数的方法)
  •   
  • InvokerParameterNameAttribute(对于具有与其中一个调用者参数匹配的字符串文字参数的方法)
  •   
  • AssertionMethodAttribute(用于断言方法)
  •   
  • AssertionConditionAttribute(用于断言方法的条件参数)
  •   
  • TerminatesProgramAttribute(对于终止控制流的方法)
  •   
  • CanBeNullAttribute(对于可以为null的值)
  •   
  • NotNullAttribute(对于不能为null的值)
  •   

答案 2 :(得分:8)

这些注释适用于ReSharper,并从JetBrains.Annotations命名空间复制。框架可以将它们放在自己的命名空间中,但是,ReSharper不会自动获取这些注释 - 您需要告诉ReSharper在选项对话框中使用自定义命名空间。一旦选择了新的命名空间,ReSharper的分析将获取属性并为您提供突出显示和警告。

答案 3 :(得分:3)

正如Anton Gogolev所指出的,可以使用PostSharp创建属性。(请注意CodeContract在方法体内使用静态方法调用)

更新2013年2月:PostSharp的新3.0版本(目前处于测试阶段)将支持 Validating parameters, fields and properties

1)文章validate-parameters-using-attributes已实施

  

public class NotEmpty:ParameterAttribute

     

public class NotNull:ParameterAttribute

     

[AttributeUsage(AttributeTargets.Parameter)]

     

公共抽象类ParameterAttribute:Attribute

     

{

public abstract void CheckParameter(ParameterInfo parameter, object value); 
     

}

它还需要一个带有方法边界方面的方法属性来处理参数属性。

2)在文章的评论中,有{Nnt / NonEmpty的very similar implementation链接

  

[return:NonNull] public SomeObject SomeMethod([NonNull] AnotherObject param1)   

源代码位于google code Torch/DesignByContract

3)http://badecho.com/2011/11/validating-method-parameters-with-postsharp/

中描述了另一个更复杂的例子