代码之家  ›  专栏  ›  技术社区  ›  Juliet

如何强制执行空检查?

  •  13
  • Juliet  · 技术社区  · 16 年前

    我在做一个大项目,即使有10到1000次的自动化测试和100%的代码覆盖率,我们也会遇到很多错误。大约95%的错误是空引用异常。

    有没有办法在编译时强制执行空检查?

    除此之外,是否有任何方法可以在单元测试中自动强制执行空检查,而不必亲自为空情况编写测试?

    12 回复  |  直到 16 年前
        1
  •  18
  •   Jon Skeet    16 年前

    你应该调查一下 Code Contracts . 静态检查器只适用于高端vs版本,但这基本上就是您所追求的。

    网上有很多资源,而且 <plug> 你也可以深入阅读第二版C- download chapter 15 for free . </plug> (这一章对于最新和最伟大的代码构建契约来说有点过时,但没有什么大不了的。)

        2
  •  4
  •   Lasse V. Karlsen    16 年前

    100%的代码覆盖率没有任何意义。

    这是一种错误的安全感。

    你唯一要衡量的是你正在执行所有的代码行。

    不是:

    • 那几行代码都是本该有的代码
    • 这些代码行运行正常(您正在测试所有的边缘案例吗?)

    例如,如果你处理火灾的程序包含一个步骤“跑出大楼”,那么即使在100%的情况下都发生了这种情况,也许更好的程序是“通知消防部门,试着阻止火灾,然后如果所有其他程序都失败了就跑出去”。

    如果您不特别进入并添加代码(代码契约(.net 4.0)或特定的if语句(<4.0),c中没有任何内置的东西可以帮助您完成这项工作。

        3
  •  1
  •   Payton Byrd    16 年前

    这不是一个技术解决方案,而是一个社交解决方案。当引用类型被外部代码(另一个方法调用等)以任何方式修改时,只需使其在您的环境中不可接受访问引用类型而不检查null。单元测试不能取代传统的代码检查。

        4
  •  1
  •   Amy B    16 年前

    有没有办法在编译时强制执行空检查?

    不。编译器无法确定运行时引用变量是否指向空。

    排除产生空值的语句(集合和返回)也不够。考虑:

    public class Customer
    {
      public List<Order> Orders {get;set;}
    }
      //now to use it
    Customer c = new Customer;
    Order o = c.Orders.First(); //oops, null ref exception;
    
        5
  •  1
  •   CurtainDog    16 年前

    防御性编程只能让你到目前为止…也许抓住这个例外,像处理其他任何异常一样处理它会更好。

        6
  •  1
  •   garik    16 年前

    1)我认为, Resharper 可以建议您检查代码中的一些关键位置。 例如,它建议添加[null reference check code]并在允许的情况下添加它。

    试试看。当然,如果你需要的话,它会增加你的经验。

    2)在开发应用程序的早期阶段,在代码中使用“Fail Fast”模式(或断言、断言)

        7
  •  0
  •   Derick Bailey    16 年前

    对于C 3,这两种情况都不可能。你必须使用一些像spec…我想C 4可能有一些内置的,但我不确定。

    规格: http://research.microsoft.com/en-us/projects/specsharp

        8
  •  0
  •   AxelEckenberger    16 年前

    在编译时不能进行空检查,因为在编译时,对象只是类型,并且只有在运行时类型才会转换为具有具体值的实例…这里是NULL。

        9
  •  0
  •   Yoann. B    16 年前
        10
  •  0
  •   Grant Palin Bob King    16 年前

    我可能错了,但我认为fxcop有一条规则建议您在代码中添加空引用检查。你可以试着通过这个工具运行你的程序集,看看它会说些什么。

        11
  •  0
  •   Noon Silk    16 年前

    退房 Gendarme ,它可以与您的测试一起运行后期生成(如果您愿意,可以在测试之前运行),并且有一些与 null 检查。你也可以写你自己的。

        12
  •  -1
  •   bryanbcook    16 年前

    .NET框架希望通过使用!修饰语。

    public void MyMethod(!string cannotBeNull)
    

    但是,唉,我们没有编译时检查。最好的办法是尽量减少外部调用方传递空值的次数,然后对面向公共的方法强制执行空检查:

    public class ExternalFacing
    {
      public void MyMethod(string arg)
      {
         if (String.IsNullOrEmpty(arg))
            throw new ArgumentNullException(arg);
    
         implementationDependency.DoSomething(arg);
       }
    }
    
    internal class InternalClass
    {
        public void DoSomething(string arg)
        {
             // shouldn't have to enforce null here.
        }
    }
    

    然后将适当的单元测试应用于外部类以期望ArgumentNullException。