C# ReSharper-使用Microsoft.Contracts时可能为空的赋值

C# ReSharper-使用Microsoft.Contracts时可能为空的赋值,c#,resharper,code-contracts,design-by-contract,microsoft-contracts,C#,Resharper,Code Contracts,Design By Contract,Microsoft Contracts,是否有任何方法可以向ReSharper指示空引用不会发生,因为契约式设计需要检查?例如,以下代码将在第7行和第8行的ReSharper中发出警告(可能为标有“NotNull”属性的实体分配“null”): private Dictionary<string, string> _Lookup = new Dictionary<string, string>(); public void Foo(string s) { Contract.Requires(!Stri

是否有任何方法可以向ReSharper指示空引用不会发生,因为契约式设计需要检查?例如,以下代码将在第7行和第8行的ReSharper中发出警告(
可能为标有“NotNull”属性的实体分配“null”):

private Dictionary<string, string> _Lookup = new Dictionary<string, string>();

public void Foo(string s)
{
    Contract.Requires(!String.IsNullOrEmpty(s));

    if (_Lookup.ContainsKey(s))
        _Lookup.Remove(s);
}

  • 重新启动Visual Studio,消息就会消失
      我想你可以,但这不是小事。看看

      他们注释了BCL类和NUnit框架(以及更多),以增强Resharpers代码检查功能

      例如,对于NUnit断言,它们使用AssertionMethodAttribute进行注释。这告诉Resharpers代码检查,如果您通过了Assert.IsNotNull(foo);然后foo不能为null,它将不再产生“可能的'null'赋值…”警告


      您可以生成一个对合同进行注释的xml文件。需要方法来指示它与断言类似。

      注意:从当前的R#8.0 EAP开始,包含此功能


      以下是当前(即NET 4.0)版本代码契约的解决方案:

      …\ExternalAnnotations\mscorlib\Contracts.xml
      中添加以下内容:

      <assembly name="mscorlib">
          <member name="M:System.Diagnostics.Contracts.Contract.Assert(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assert(System.Boolean, System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assume(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assume(System.Boolean, System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires``1(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires``1(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Invariant(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Invariant(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
      </assembly>
      
      
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      
      删除断言时,消息消失的原因是R#在默认情况下以“乐观”模式工作。它假定所有内容都是非null的,直到您执行了一些指示它实际上可以为null的操作。这就是将调用添加到
      String.IsNullOrEmpty
      时发生的情况。您正在声明
      s
      实际上可以为null。它只是没有意识到如果出现这种情况,
      Contract.Requires
      方法将停止执行,但是您已经用注释解决了这个问题


      在R#5.0中,您可以更改为悲观模式,在每个角落都假设最坏的情况。

      我想补充一点,对于编写自己的断言方法的人,您可以在不使用外部XML文件的情况下包含这些属性。在Visual Studio中,转到
      ReSharper>Options>code注释
      ,然后单击
      将默认实现复制到剪贴板
      按钮。然后创建一个新文件(在解决方案中的任何位置),并从剪贴板粘贴代码。现在,您可以创建如下方法:

      public class Require
      {
          [AssertionMethod]
          public static void That(
              [AssertionCondition(AssertionConditionType.IS_TRUE)] 
              bool requiredCondition,
              string message = null)
          {
              ...
          }
      ...
      }
      
      现在,对
      Require.That(a!=null)
      的任何调用都将向ReSharper指示,如果
      a
      为null,您将无法通过此行。与ExternalAnnotations技术不同,这将适用于使用您的方法的任何人,而无需他们做任何额外的工作

      更新 从版本7开始,Resharper已经更改了他们的合同注释模型。下面是上述方法现在的样子:

      public class Require
      {
          [ContractAnnotation("requiredCondition:false => halt")]
          public static void That(
              bool requiredCondition,
              string message = null)
          {
              ...
          }
      ...
      }
      

      我使用了Porges的XML,并为Assert和Aspect方法添加了注释。如果其他人想添加更多的方法,我将把这个答案放到wiki上

      <assembly name="mscorlib">
          <member name="M:System.Diagnostics.Contracts.Contract.Assert(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assert(System.Boolean, System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assume(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assume(System.Boolean, System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires``1(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires``1(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Invariant(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Invariant(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
      </assembly>
      
      
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      
      TL;DR-向项目中添加条件编译符号
      CONTRACTS\u FULL

      Contract.Requires(…)
      方法为空且已禁用,除非启用并使用代码联系人重写器。通过手动运行重写器,或者(通常)通过Visual Studio项目属性启用重写器,您将在编译和重写的二进制文件中保留
      契约。需要(…)
      代码。您知道该代码可以工作,并且忽略Resharper警告,您可以运行它并进行测试

      那有什么问题?Resharper不知道代码契约正在运行,因为它们实际上只在(后期)编译时注入。在Resharper看来,它的禁用方式与
      DEBUG
      预处理器符号的工作方式以及Visual Studio如何使代码中不属于已编译二进制文件的区域变灰相同

      #ifdef调试
      WriteLine(“我处于调试模式,所以这可能是一个调试构建。”);
      #否则
      WriteLine(“让我们假设这是一个发布版本。”);
      #恩迪夫
      
      根据(第2章,第一段)和
      ContractExtensions.cs
      (包含在code Contracts安装文件夹中)中的源代码,
      Contracts\u FULL
      需要在编译之前进行设置。使用和忽略(编译时不包括),除非设置了标志。Resharper尊重此标志,并假定
      <assembly name="mscorlib">
          <member name="M:System.Diagnostics.Contracts.Contract.Assert(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assert(System.Boolean, System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assume(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assume(System.Boolean, System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires``1(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires``1(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Invariant(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Invariant(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <parameter name="condition">
                  <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                      <argument>0</argument>
                  </attribute>
              </parameter>
          </member>
      </assembly>
      
      <assembly name="System.Diagnostics.Contracts">
          <member name="M:System.Diagnostics.Contracts.Contract.Assert(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <attribute ctor="M:JetBrains.Annotations.ContractAnnotationAttribute.#ctor(System.String)">
                  <argument>condition:false=&gt;halt</argument>
              </attribute>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assert(System.Boolean, System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <attribute ctor="M:JetBrains.Annotations.ContractAnnotationAttribute.#ctor(System.String)">
                  <argument>condition:false=&gt;halt</argument>
              </attribute>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assume(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <attribute ctor="M:JetBrains.Annotations.ContractAnnotationAttribute.#ctor(System.String)">
                  <argument>condition:false=&gt;halt</argument>
              </attribute>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Assume(System.Boolean, System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <attribute ctor="M:JetBrains.Annotations.ContractAnnotationAttribute.#ctor(System.String)">
                  <argument>condition:false=&gt;halt</argument>
              </attribute>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <attribute ctor="M:JetBrains.Annotations.ContractAnnotationAttribute.#ctor(System.String)">
                  <argument>condition:false=&gt;halt</argument>
              </attribute>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires``1(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <attribute ctor="M:JetBrains.Annotations.ContractAnnotationAttribute.#ctor(System.String)">
                  <argument>condition:false=&gt;halt</argument>
              </attribute>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <attribute ctor="M:JetBrains.Annotations.ContractAnnotationAttribute.#ctor(System.String)">
                  <argument>condition:false=&gt;halt</argument>
              </attribute>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Requires``1(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <attribute ctor="M:JetBrains.Annotations.ContractAnnotationAttribute.#ctor(System.String)">
                  <argument>condition:false=&gt;halt</argument>
              </attribute>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Invariant(System.Boolean)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <attribute ctor="M:JetBrains.Annotations.ContractAnnotationAttribute.#ctor(System.String)">
                  <argument>condition:false=&gt;halt</argument>
              </attribute>
          </member>
          <member name="M:System.Diagnostics.Contracts.Contract.Invariant(System.Boolean,System.String)">
              <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
              <attribute ctor="M:JetBrains.Annotations.ContractAnnotationAttribute.#ctor(System.String)">
                  <argument>condition:false=&gt;halt</argument>
              </attribute>
          </member>
      </assembly>