2015-06-22 12 views
2

我們有一個項目,我們使用StyleCop和代碼分析來驗證代碼的結構。我們已將警告視爲兩種機制的錯誤。爲什麼在C#項目中進行/優化會生成更多的代碼分析警告,而不是啓用此功能?

然而,我們發現了一種我們無法解釋的平庸行爲。我們有一個調試和發佈配置。在我們的調試配置中,我們沒有得到一個CA警告,而在我們的發佈配置中收到此警告。我們開始考慮這兩種配置之間的差異,並且我們發現優化複選框是爲什麼我們在發佈期間得到此警告但不在調試過程中的差異。

我們有以下配置。

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> 
    <DebugSymbols>true</DebugSymbols> 
    <DebugType>full</DebugType> 
    <Optimize>false</Optimize> 
    <OutputPath>bin\Debug\</OutputPath> 
    <DefineConstants>DEBUG;TRACE</DefineConstants> 
    <ErrorReport>prompt</ErrorReport> 
    <WarningLevel>4</WarningLevel> 
</PropertyGroup> 
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> 
    <DebugType>pdbonly</DebugType> 
    <Optimize>true</Optimize> 
    <OutputPath>bin\Release\</OutputPath> 
    <DefineConstants>TRACE</DefineConstants> 
    <ErrorReport>prompt</ErrorReport> 
    <WarningLevel>4</WarningLevel> 
</PropertyGroup> 

當我們將優化值設置爲true以進行調試時,我們還會發出CA警告。當我們將此設置爲false時,警告消失。這也適用於警告CA1806。無論優化值如何,其他CA警告都能正確顯示。

觸發此警告的代碼是以下代碼。這只是測試代碼,但它模擬了我們的真實情況。一個分配了默認值但從未在任何代碼中使用的變量。

public CourseService(IOrtContext context) 
{ 
    this.context = context; 
    var defaultDate = new DateTime(1900, 1, 1); 
} 

那麼,有沒有人知道爲什麼CA1806顯示取決於是否啓用優化?

+0

警告是合法的,因爲文檔說它是在創建新對象時觸發的,但從未使用*。在調試模式下,您是否正面使用'defaultDate'也不會使用? –

+0

該警告確實是合法的。我預計它也會發生在這個測試代碼中,但通過上面的調試配置,這個警告不會出現。我確定這個defaultDate不用於任何調試模式代碼。上面的代碼是我正在使用的確切代碼。這個變量在構造函數中作爲範圍(用於測試),並在構造函數中作爲最後一行。 –

回答

0

我認爲這是因爲優化器完全忽略了分配到defaultDate

在調試模式下,一個新的DateTime被實例化並分配給defaultDate局部變量:

var defaultDate = new DateTime(1900, 1, 1); 

分配被認爲是在DateTime實例的「使用」,所以CA1806不提高,甚至如果defaultDate隨後不使用。

在另一方面,優化elides在釋放模式中的分配(和局部變量):

/* var defaultDate = */ new DateTime(1900, 1, 1); 

因此DateTime實例不被認爲是「已使用」了,並CA1806上升。

0

在這裏隨意扔石頭...調試的簡單代碼:http://goo.gl/8TXmE9和版本:http://goo.gl/XRBfQp

在調試模式下,本地變量的生存期是「擴展」的,直到方法結束,以便它們更易於調試。在發佈模式下,這不會發生。變量被大量釋放。如果您在調試模式或釋放模式下編譯程序並嘗試調試它,則可以看到它...在釋放模式下,有時某些變量無法訪問,因爲它們已經結束了它們的生命週期。

這可以在釋放IL代碼可看到:

IL_0007: newobj instance void [mscorlib]System.DateTime::.ctor(int32, int32, int32) 
IL_000c: pop 

new DateTime()返回的是pop PED出棧的立即。 CA1806可以輕鬆檢測到它。

在調試模式下,該值不會彈出堆棧。分析檢查它是否在某處使用會相當複雜,可能還沒有完成。

相關問題