簡體   English   中英

使用string.IsNullOrWhiteSpace時如何處理Code Contracts警告CC1036?

[英]How to deal with Code Contracts warning CC1036 when using string.IsNullOrWhiteSpace?

我有以下代碼合同:

public void F(string x)
{
    Contract.Requires(!string.IsNullOrWhiteSpace(x));

    throw new NotImplementedException();
}

編譯時,我收到以下警告:

警告CC1036:在方法合同中檢測到方法'System.String.IsNullOrWhiteSpace(System.String)'沒有[Pure]的調用[...]

怎么處理呢?

奇怪的是,我也在使用string.IsNullOrEmpty ,在其他合同中也沒有標記為[Pure] ,並且重寫器沒有問題。

我的合同重寫版的版本是1.9.10714.2。

這是我正在使用的String類的實現的相關部分(從元數據中檢索):

#region Assembly mscorlib.dll, v4.0.0.0
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll
#endregion

using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;

namespace System
{
    // Summary:
    //     Represents text as a series of Unicode characters.To browse the .NET Framework
    //     source code for this type, see the Reference Source.
    [Serializable]
    [ComVisible(true)]
    public sealed class String : IComparable, ICloneable, IConvertible, IEnumerable, IComparable<string>, IEnumerable<char>, IEquatable<string>
    {

    // [...]

        //
        // Summary:
        // [...]
        public static bool IsNullOrEmpty(string value);
        //
        // Summary:
        // [...]
        public static bool IsNullOrWhiteSpace(string value);

為什么缺少[Pure]屬性?

這里我們有兩點:

1.為什么IsNullorWhiteSpace函數的字符串類中缺少[Pure]屬性?

2.如何解決CC1030警告問題?

我會嘗試討論兩者。

1.為什么缺少[Pure]屬性? 它並沒有丟失,元數據似乎沒有顯示出來。

這可能不會在以前版本的.NET FX中標記為Pure ,因為他們說:

是的, 我們需要讓我們的檢查器對禁用pragma敏感 ...

嘆。

我們目前沒有實現,但我已將其添加到我們的工作列表中。

請參閱這里 5歲的討論。

但是在最新的FX(4.6.1)中已將其標記為Pure ,請參閱.NET Framework 4.6.1 ,即新的string類代碼

[Pure]
public static bool IsNullOrWhiteSpace(String value) {
    if (value == null) return true;

    for(int i = 0; i < value.Length; i++) {
        if(!Char.IsWhiteSpace(value[i])) return false;
    }

    return true;
}

那么為什么CC1036?

此警告“CC1036”來自CodeContracts ,開發人員昨天只打開此問題( 請參閱此處 )。

現在為什么元數據不會吐出Pure屬性,這是一個不同的問題,就像Equals方法一樣, Pure被添加但是只有SecuritySafeCritical顯示在元數據代碼中。

[SecuritySafeCritical]
public static bool Equals(String a, String b, StringComparison comparisonType);

同樣的問題適用於Invariant() 給定以下代碼,將顯示相同的警告:

private string testString = "test";

[ContractInvariantMethod]
private void TestInvariant()
{
     Contract.Invariant(!string.IsNullOrWhiteSpace(testString));
}

怎么解決?

正如其他人也建議的那樣,創建另一種方法,將其標記為Pure並在合同條件中調用它。

通過一個純粹的代表將使警告消失。 Predicate<T>已標記為純,因此您可以使用它來解決該問題:

// Workaround for https://github.com/Microsoft/CodeContracts/issues/339
public Predicate<string> IsNullOrWhiteSpace = string.IsNullOrWhiteSpace;

public void F(string x)
{
    Contract.Requires(!IsNullOrWhiteSpace(x));

    throw new NotImplementedException();
}

雖然string.IsNullOrWhiteSpace丑陋,但你可以用擴展方法包裝函數string.IsNullOrWhiteSpace並將這個新函數標記為Pure

我剛剛遇到了完全相同的問題。 我正在使用VS2015,所以它似乎與VS版本無關。 我還在.NET 4.0,4.5.1和4.6上測試了完全相同的代碼,但未收到警告。

像其他人在我之前評論過的那樣, IsNullOrWhiteSpace在.NET 4.6.1中被標記為[Pure] ,並且默認情況下應該被Code Contracts認為是純的,因為它位於System.String命名空間中。 這使它看起來像一個bug,所以我已經向Code Contracts提交了一個關於這個的問題 ,所以運氣好的話我們很快就會看到一個正式答案。

當我們等待答案時,有可能(如@Jaco建議的那樣)將其包裝在擴展方法中並將其標記為Pure (可選)您可以禁止該特定方法的警告,如下所示:

[SuppressMessage("Microsoft.Contracts", "CC1036", Justification = "string.IsNullOrWhiteSpace is Pure")]

...但請注意,這也會在同一方法中禁止來自其他合同定義的此警告。

實際上,這是.NET 4.6+編譯方式的問題。 請參閱此GitHub拉取請求

我能夠通過修改以下文件來解決這個問題:

  • 對於Visual Studio 2013:
    • C:\\Program Files (x86)\\Microsoft\\Contracts\\MsBuild\\v12.0\\Microsoft.CodeContracts.Targets
  • 對於Visual Studio 2015:
    • C:\\Progarm Files (x86)\\Microsoft\\Contracts\\MsBuild\\v14.0\\Microsoft.CodeContracts.Targets

在這兩個文件中,確保第一個<Choose>元素的<Otherwise>子元素具有以下內容:

...
<Choose>
  <When Condition="'$(TargetFrameworkIdentifier)' == 'Silverlight'">
     ...
  </When>
  <Otherwise>
    <Choose>
      <When Condition="'$(TargetFrameworkVersion)' == 'v4.0">
        <PropertyGroup>
          <CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.0</CodeContractsReferenceAssemblyLibPath>
        </PropertyGroup>
      </When>
      <When Condition="'$(TargetFrameworkVersion)' == 'v4.5'">
        <PropertyGroup>
          <CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.5</CodeContractsReferenceAssemblyLibPath>
        </PropertyGroup>
      </When>
      <When Condition="'$(TargetFrameworkVersion)' == 'v4.5.1'">
        <PropertyGroup>
          <CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.5</CodeContractsReferenceAssemblyLibPath>
        </PropertyGroup>
      </When>
      <When Condition="'$(TargetFrameworkVersion)' == 'v4.5.2'">
        <PropertyGroup>
          <CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.5</CodeContractsReferenceAssemblyLibPath>
        </PropertyGroup>
      </When>
      <When Condition="'$(TargetFrameworkVersion)' == 'v4.6'">
        <PropertyGroup>
          <CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.5</CodeContractsReferenceAssemblyLibPath>
        </PropertyGroup>
      </When>
      <When Condition="'$(TargetFrameworkVersion)' == 'v4.6.1'">
        <PropertyGroup>
          <CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.5</CodeContractsReferenceAssemblyLibPath>
        </PropertyGroup>
      </When>
      <Otherwise>
        <PropertyGroup>
          <CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v3.5</CodeContractsReferenceAssemblyLibPath>
        </PropertyGroup>
      </Otherwise>
    </Choose>
  </Otherwise>
</Chose>
...

對這些文件進行這些更改后(根據上面引用的GitHub pull請求),我不再收到使用String.IsNullOrWhiteSpace Code Contracts靜態分析警告。

應該注意的是,引用的pull請求已經合並到GitHub上的Code Contracts的主代碼中; 他們還沒有發布包含這些更改的新版本。

此外,對於那些擔心更改“系統文件”的人,請不要這樣做。 當下一版本的Code Contracts發布時,它將安裝這些文件的更新版本 - 並且希望包含這些更改,並且所有這些都將適用於全世界。 (當然,除非更改未包括在內 - 在這種情況下,您將回到此處參考此帖子以再次進行更改;)大聲笑。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM