Introduction
.NET Compiler generated warnings (Code Analysis warnings) messages may not be meaningful in the development cycle, but once the code review is done you may need to suppress these compiler generated warning messages. To achieve warning message suppression you can either use In Source Suppression (ISS) allowing .NET developers to write code for warning suppression or use Microsoft Visual Studio Project menu to suppress the warnings. In this article, we will be discuss different techniques of compiler warning suppression.
In Source Suppression (ISS)
In Source Suppression is achieved by using the SuppressMessage
attribute either defined on top of your classes or Methods. SuppressMessage
is an attribute defined in Intermediate Language (IL) metadata. Syntax to follow:
<Code>
[Scope:SuppressMessage(“Rule Category”, “Rule Id”, “Justification”, “MessageId”, Scope = “Scope”, Target = “Target”)]
</Code>
- Rule Category – for example Microsoft.Design, Microsoft.Performance, Microsoft.Usage etc. Name of the Category for which the rule will be defined.
- Rule Id – For example CA1801:ReviewUnusedParameters, CA1804:RemoveUnusedLocals , CA1019:DefineAccessorsForAttributeArguments etc. The rule id can be defined in 2 different formats, the short name is CAXXXX and the long name is CAXXXX:FriendlyTypeName. These are the warning numbers.
- Justification – The Reason for suppressing the message. This justification should be meaningful.
- Scope – It’s the range, values are like Module, Namespace, Resource, Type, Member and Parameter.
- Target – Like Microsoft.Tools.FxCop.Type..ctor(). It’s the identifier on which the warning is being suppressed.
If you see the metadata for the SuppressMessage
attribute. It’s a class called SuppressMessageAttribute
In the following Section I have added the metadata for the SuppressMessageAttribute
class generated by Microsoft Visual Studio editor.
Diagram – How to see the Metadata for SuppressMessage attribute
SuppressMessageAttribute Class metadata as follows:
<Code>
using System;
using System.Diagnostics;namespace System.Diagnostics.CodeAnalysis
{
// Summary:
//Suppresses reporting of a specific static analysis tool rule violation,
allowing
//multiple suppressions on a single code artifact.
[AttributeUsage(32767, Inherited = false, AllowMultiple = true)]
[Conditional(“CODE_ANALYSIS”)]
public sealed class SuppressMessageAttribute : Attribute
{
// Summary:
// Initializes a new instance of the
//System.Diagnostics.CodeAnalysis.SuppressMessageAttribute
// class, specifying the category of the static analysis tool and the
//identifier
// for an analysis rule.
//
// Parameters:
// category:
// The category for the attribute.
//
// checkId:
// The identifier of the analysis tool rule the attribute applies to.
public SuppressMessageAttribute(string category, string checkId);// Summary:
// Gets the category identifying the classification of the attribute.
//
// Returns:
// The category identifying the attribute.
public string Category { get; }
//
// Summary:
// Gets the identifier of the static analysis tool rule to be
// suppressed.
//
// Returns:
// The identifier of the static analysis tool rule to be suppressed.
public string CheckId { get; }
//
// Summary:
// Gets or sets the justification for suppressing the code analysis
// message.
//
// Returns:
// The justification for suppressing the message.
public string Justification { get; set; }
//
// Summary:
// Gets or sets an optional argument expanding on exclusion criteria.
//
// Returns:
// A string containing the expanded exclusion criteria.
public string MessageId { get; set; }
//
// Summary:
//Gets or sets the scope of the code that is relevant for the attribute.
//
// Returns:
// The scope of the code that is relevant for the attribute.
public string Scope { get; set; }
//
// Summary:
// Gets or sets a fully qualified path that represents the target of the
//attribute.
//
// Returns:
// A fully qualified path that represents the target of the attribute.
public string Target { get; set; }
}
}</Code>
You can also maintain a global level Suppression file that does not have a specific target. Assembly level violations can be included in this file.
The following is an example of global level Suppression file (GlobalSuppressions.cs
) for MVC 2.0 RC.
<Code>
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
//
// To add a suppression to this file, right-click the message in the
// Error List, point to “Suppress Message(s)”, and click
// “In Project Suppression File”.
// You do not need to add suppressions to this file manually.[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Design”, “CA1033:InterfaceMethodsShouldBeCallableByChildTypes”, Scope = “member”, Target = “System.Web.Mvc.TempDataDictionary.#System.Collections.Generic.ICollection`1<System.Collections.Generic.KeyValuePair`2<System.String,System.Object>>.Contains(System.Collections.Generic.KeyValuePair`2<System.String,System.Object>)”,
Justification = “There are no defined scenarios for wanting to derive from this class, but we don’t want to prevent it either.”)]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Design”, “CA1033:InterfaceMethodsShouldBeCallableByChildTypes”, Scope = “member”, Target = “System.Web.Mvc.TempDataDictionary.#System.Collections.Generic.ICollection`1<System.Collections.Generic.KeyValuePair`2<System.String,System.Object>>.CopyTo(System.Collections.Generic.KeyValuePair`2<System.String,System.Object>[],System.Int32)”,
Justification = “There are no defined scenarios for wanting to derive from this class, but we don’t want to prevent it either.”)]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Design”, “CA1033:InterfaceMethodsShouldBeCallableByChildTypes”, Scope = “member”, Target = “System.Web.Mvc.TempDataDictionary.#System.Collections.Generic.ICollection`1<System.Collections.Generic.KeyValuePair`2<System.String,System.Object>>.IsReadOnly”,
Justification = “There are no defined scenarios for wanting to derive from this class, but we don’t want to prevent it either.”)]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Design”, “CA1020:AvoidNamespacesWithFewTypes”, Scope = “namespace”, Target = “System.Web.Mvc.Ajax”,
Justification = “Helpers reside within a separate namespace to support alternate helper classes.”)]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Portability”, “CA1903:UseOnlyApiFromTargetedFramework”, MessageId = “System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”,
Justification = “MVC has a .NET Framework 3.5 SP1 dependency.”)]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Portability”, “CA1903:UseOnlyApiFromTargetedFramework”, MessageId = “System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”,
Justification = “MVC has a .NET Framework 3.5 SP1 dependency.”)]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Portability”, “CA1903:UseOnlyApiFromTargetedFramework”, MessageId = “System.ComponentModel.DataAnnotations, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”,
Justification = “MVC has a .NET Framework 3.5 SP1 dependency.”)]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Portability”, “CA1903:UseOnlyApiFromTargetedFramework”, MessageId = “System.Data.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”,
Justification = “MVC has a .NET Framework 3.5 SP1 dependency.”)]</Code>
For namespace level suppression you can use the following declaration:
<Code>[Module: SuppressMessage (“Microsoft.Performance”, “CA1801: ReviewUnusedParameters”, Scope = “namespace”, Justification = “Performance of Session Variable” Target = “System.Web.SessionState”)]
</Code>
Compiler warnings can be directly suppress from VS editor if you are using Visual Studio Team System. For that Open the Error List from View menu and Select all the warnings you want to Suppress. Right click and Select Suppress Message(s), now either click ‘In Source’ or ‘In Project Suppression File’.
Suppression Warnings using #pragma
#pragma Warning Disable and # pragma warning Enable specifies are supported from Visual Studio 2005 and onwards.
#pragma warning disable 0219,0414,169
The above specifies can be used for disabling warning number 0219,0414,169.
</Code>
#define CODE_ANALYSIS
using System;
using System.Diagnostics.CodeAnalysis;namespace CodeAnalysisSample
{
#pragma warning disable 0219,0414,169
class Library
{
static void FileNode(string name, bool isChecked)
{
string fileIdentifier = name;
string fileName = name;
string version = String.Empty;
}
public static void Main()
{}
}
}
<Code>
To make 0219 warning number enable again, use the following directive.
#pragma warning (default: 0219)
Or
#pragma warning restore 0219
To report 0414 warning as error, use the following statement.
#pragma warning (error: 0414)
Suppression Warnings from the Microsoft Visual Studio Project menu
You can also configure Compiler generated warnings From Visual Project properties menu. Under the Build Tab you will get “Errors and Warnings”. You can change the warning levels and you can suppress specific warnings using /nowarn directive.
To suppress warning CS0028, you could specify /nowarn:28
.
If you want the compiler to treat all warnings as errors, select the ‘All’ option from “Treat warnings as errors”.
You can also specify specific warning numbers.
Diagram – Suppress Compiler warnings from Project Properties
In Microsoft Visual Studio 2008 Project Properties you will get lots of other options for Disabling Compiler warnings. Under Warning Configuration a condition list appears. You can disable a specific type of warning message by selecting ‘None’ from the dropdown or you can ask the Compiler to treat as an error by selecting ‘Error Option’.
Diagram – Visual Studio 2008 Project Properties For suppressing compilation warnings
Conclusion
It’s always good practice to do a proper code review after the development cycle. Most of the compiler generated warnings are for unused local or global variables and you should not suppress those warnings. Disabling warnings is always discouraged in a production environment. Warning suppression is intended only for analysis when you are actually trying to isolate a problem, or when you lay out the basic code/initial code structure. In all other cases, .NET developers should avoid suppressing compiler warnings.