141

In Visual Studio, I can select the "Treat warnings as errors" option to prevent my code from compiling if there are any warnings. Our team uses this option, but there are two warnings we would like to keep as warnings.

There is an option to suppress warnings, but we DO want them to show up as warnings, so that won't work.

It appears that the only way to get the behavior we want is to enter a list of every C# warning number into the "Specific warnings" text box, except for the two we want treated as warnings.

Besides the maintenance headache, the biggest disadvantage to this approach is that a few warnings do not have numbers, so they can't be referenced explicitly. For example, "Could not resolve this reference. Could not locate assembly 'Data....'"

Does anyone know of a better way to do this?


Clarifying for those who don't see immediately why this is useful. Think about how most warnings work. They tell you something is a little off in the code you just wrote. It takes about 10 seconds to fix them, and that keeps the code base cleaner.

The "Obsolete" warning is very different from this. Sometimes fixing it means just consuming a new method signature. But if an entire class is obsolete, and you have usage of it scattered through hundreds of thousands of lines of code, it could take weeks or more to fix. You don't want the build to be broken for that long, but you definitely DO want to see a warning about it. This isn't just a hypothetical case--this has happened to us.

Literal "#warning" warnings are also unique. I often want to check it in, but I don't want to break the build.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
Neil
  • 7,227
  • 5
  • 42
  • 43
  • Can you please put spaces into your big list of numbers? It has stuffed up the line wrapping. – Ray Nov 06 '08 at 00:00
  • Gawd I hate complicated rules that are made up by people, oftentimes to soothe some specific person's ego. – Jon Limjap Dec 19 '08 at 08:53
  • 25
    I see his point about the obsolete warning, this isn't arbitrary. – Ed S. Jan 22 '09 at 06:43
  • In my experience allowing even one warning in your build is like adding a first async/await. Soon there will be tens of them. In all setups I remember a developer is able to see less then 10 warnings in the Error List window in VS. I can bet that as soons as you have more than 5 warnings the vast majority of devs in a team will not be able to spot a new one - in you setup it means that they will not spot the warning that the method is obsolete which defies the whole purpose of having it a warning :) What is your experience with this Neil? – tymtam Dec 21 '16 at 23:58
  • 1
    @mayu, it is a conundrum. Many times, I have seen warnings go ignored for a long time. But in the end, either you show the warning or you show nothing at all. If you are showing the warning, at least there is a chance of someone learning something useful from it. If you treat most warnings as errors, then the few that are left can get more attention. – Neil Mar 10 '17 at 03:23

11 Answers11

177

You can add a WarningsNotAsErrors-tag in the project file.

<PropertyGroup>
    ...
    ...
    <WarningsNotAsErrors>618,1030,1701,1702</WarningsNotAsErrors>
</PropertyGroup>

Note: 612 and 618 are both warnings about Obsolete, don't know the difference but the project i'm working on is reporting Obsolete with warning 618.

herohuyongtao
  • 49,413
  • 29
  • 133
  • 174
SvenL
  • 1,795
  • 1
  • 11
  • 3
  • 25
    The difference between 612 and 618 is the comment of the ObsoleteAttribute. An ObsoleteAttribute without comment generates the error 612, and one with a comment generates 618. – Marco Spatz Mar 30 '11 at 11:00
  • @MarcoSpatz Exactly. Then we can treat `[Obsolete]` members where the `message` is `null` as errors, while we let those where the `message` is set remain warnings only. If the `error` parameter is set to `true` in the `ObsoleteAttribute`, a CS0619 is generated instead. This seems to not work if `message` is `null` (but who would do `[Obsolete(null, true)]` anyway?). – Jeppe Stig Nielsen Nov 07 '13 at 15:51
  • For F#, use ``--warnaserror-:618,1030`` on the Build->Other flags field. This project option is not yet implemented for F# projects. https://github.com/Microsoft/visualfsharp/issues/3395 – Asik Mar 13 '18 at 18:36
  • 2
    Good to know "WarningsNotAsErrors" exists. It should be available in project settings without to edit manually the file. Thanks. – AFract Oct 23 '18 at 09:03
  • 1
    Microsoft really screwed this up (and 11 years later, hasn't fixed things!). The project settings change ``, which is inferior in most cases and failed to put `` in the UI. Kudos. – user2864740 Feb 12 '20 at 17:41
  • It doesn't show up in Intellisense either, but works like a charm. – RubberDuck Jul 02 '20 at 13:14
  • Thanks for this. Is there any way to scope this to just specific files, versus the whole project ? I'm a big fan of warnings and errors and don't want to squelch legitimate signal. .. Hm, according to [these docs](https://learn.microsoft.com/en-us/visualstudio/msbuild/propertygroup-element-msbuild?view=vs-2019), no: `` is a property and must go in a PropertyGroup, and PropertyGroups must go in Projects. – orion elenzil May 28 '21 at 17:10
  • Thanks, this works for me as well. I wonder, is there a way to wildcard the errors? I want all warning to be treated as errors except those coming from SonarQube (that start with S, e.g. S2190, S2200 etc.) – Siarhei Machel Aug 02 '21 at 08:23
15

/warnaserror /warnaserror-:618

  • 1
    Thank you for your input. Even though they don't solve the IDE problem, these are the most helpful comments so far. – Neil Dec 29 '08 at 06:56
  • 2
    Where do you add this? – checho Apr 07 '15 at 08:34
  • @checho, those switches would be added on the command line when calling msbuild. For our purposes, the top answer is more helpful, because we can bake it into the project instead of having to modify the way we call msbuild. – Neil Jan 27 '16 at 14:42
  • 1
    Doesn't work with MSBuild 15.9.21+g9802d43bc3: `MSBUILD : error MSB1001: Unknown switch. Switch: /warnaserror-:618` – Paul B. Nov 13 '19 at 07:39
8

In Visual Studio 2022 we have a new Project Properties UI which includes an editor for this.

Under Build | Errors and Warnings if you set Treat warnings as errors to All, then another property appears which allows you to exempt specific warnings from being treated as errors:

enter image description here

This will add the following property to your project:

<WarningsNotAsErrors>618,1030,1701,1702</WarningsNotAsErrors>
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • 2
    Drew, thanks for letting us know! It's good to know there's finally a highly-discoverable solution. I'm changing this to the accepted answer. – Neil May 16 '21 at 15:31
  • 1
    This new UI allows us to add and modify the Project Properties UI much more easily than in the legacy pages. You can try it out in the most recent VS2019 preview builds (if you turn the "Use Updated Project Properties UI" feature flag on in the options window) until VS2022 is released. – Drew Noakes May 16 '21 at 23:24
  • In case you're wondering, this doesn't seem to be the case for .NET Framework projects in VS 2022. – Eike Nov 08 '22 at 08:36
  • 1
    @Eike yes, this is only for SDK-style projects. Note that you can modify an SDK-style project to target .NET Framework easily enough, though it's not officially supported by Microsoft. – Drew Noakes Nov 10 '22 at 08:10
5

or more specifically, in your case:

/warnaserror /warnaserror-:612,1030,1701,1702

this should treat all warnings as errors except for the ones in your comma separated list

2

Why do you want to keep seeing warnings that you are not treating as errors? I am confused about why this is desirable - either you fix them or you don't.

Would two different build/solution files work - or a script to copy one and then so modify the warnings/warning level be suitable. It seems that perhaps you want some executions of the compiler to squawk, but others you want to keep going.

So different compiler switches seems like a good way to go. You could do this with different targets - one labeled debug or release and the others labeled suitably about the warnings.

Tim
  • 20,184
  • 24
  • 117
  • 214
  • 7
    Most warnings happen because of a simple confusion in my code (e.g. I declared a variable that I don't use). An Obsolete warning often happens because of a change in someone else's code. Fixing this could take weeks of development. #warning is a warning I want in the code (likely a long-term fix). – Neil Nov 06 '08 at 17:25
  • 4
    In other words, there are warnings that I don't want to break my build. If #warning breaks the build, then I can't ever check one in. If Obsolete breaks the build, then another team we depend on could unknowingly break our team's build just by adding an obsolete attribute. – Neil Nov 06 '08 at 17:30
  • @Neil I agree with some of your arguments, but removing a var you don't use doesn't take much time *AND* you definitely want to know that another team made something obsolete. – tymtam Dec 19 '16 at 22:02
  • @mayu, thanks for your comment. I agree about a var you don't use. That's why I would have the compiler treat it as an error. I also agree you do want to know when something is obsolete. But if it takes prohibitively long to refactor something obsolete our of your code, your choices are 1) Treat this warning as a warning 2) Let your build stay broken for a long time 3) Some other solution like turning off warnings as errors. With most warnings as errors, your warnings list is likely to stay short, so you are more likely to notice when they do show up. What is your preferred solution? – Neil Dec 20 '16 at 23:24
  • @NeilWhitaker - I can see 4) pragma disable the warning in places where it needs to stay the way it is (not recommended, often abused - very simiar to just muting warnings) 5) make the other team provide backward compatiblity untill others moved away from the old way of doing things. Why would they obsolete something that could take weeks of dev for another team to address? If another team uses it (and will for a long time) is it really obsolete? I see this scenario like this: if something is obsoleted it's a big deal and it should be addressed. – tymtam Dec 21 '16 at 23:50
  • 2
    @mayu, another team (whether within the same company or outside it) may legitimately want to communicate that a class, method, other component is being phased out over some period of time. Adding an attribute is a good way to signal this to consumers of a library. I don't see it as troublesome to do this. In fact, adding the attribute as early as possible is a good way to make sure others are aware of future changes. – Neil Dec 29 '16 at 06:05
  • 1
    Sometimes Microsoft obsoletes things. – PRMan Jan 13 '20 at 19:36
2

I'm using treat warnings as errors.

In a rare cases, when some acceptable warning shows up (i.e. referencing obsolete member, or missing documentation on XML serialization classes), then it has to be explicitly suppressed with #pragma disable (and optionally reason for not having a clean code could be provided as a comment along).

Presence of this directive also allows to find out, who accepted this warning violation (by "blame" action of version control) in case there are some questions.

Rinat Abdullin
  • 23,036
  • 8
  • 57
  • 80
  • 3
    I use this also, although it doesn't solve the problems mentioned in my description. I want certain warnings treated as warnings, not hidden. – Neil Oct 06 '09 at 22:53
2

What has been omitted from the discussions so far is that setting the properties (TreatWarningsAsErrors as well as WarningsNotAsErrors) is provided per build configuration. This gives you the ability to disable warnings being treated as errors while working out the optimal coding solution (in Debug configuration) but also be forced to take care of the warnings in the Release configuration. For example

   <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <DebugType>full</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <ErrorReport>prompt</ErrorReport>
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
    <NoWarn>1701;1702;1803</NoWarn>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <Optimize>true</Optimize>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <ErrorReport>prompt</ErrorReport>
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
  </PropertyGroup>```
1

Why not simply have a rule saying "Whoever checks in code with any warning inside it other than 612, 1030, 1701 or 1702 in it must go to the whiteboard and write a hundred times 'I will not check in code with disallowed warnings again.'"

erikkallen
  • 33,800
  • 13
  • 85
  • 120
  • 9
    Good luck enforcing that... Treating warnings as errors is a very important step to increase overall code quality *and* it will force devs to actually fix their code! All hail automation, manual labor is *so* 20th-century:ish! – Andreas Magnusson Oct 05 '12 at 10:12
  • 1
    @AndreasMagnusson If only the lack of warnings actually ensured the quality of code.. – user2864740 Nov 30 '15 at 03:01
  • 3
    @user2864740: Agreed, there are no silver bullets. But it's an all too common fallacy to reject something useful on the premise that it's not a silver bullet. – Andreas Magnusson Nov 30 '15 at 08:56
1

Treat all but some warnings as error

You should set TreatWarningAsErrors to true and exclude some warnings as WarningNotAsErrors :

<PropertyGroup>
    <TreatWarningAsErrors>true</TreatWarningsAsErrors>
    <WarningsNotAsErrors>618,1030,1701,1702</TreatWarningsAsErrors>
</PropertyGroup>

Treat just some warnings as error

Also you may want to treat just some warning as error using WarningsAsErrors :

<PropertyGroup>
    <TreatWarningAsErrors>false</TreatWarningsAsErrors>
    <WarningsNotAsErrors>1703,1704</TreatWarningsAsErrors>
</PropertyGroup>

You can find more here.

Hossein Narimani Rad
  • 31,361
  • 18
  • 86
  • 116
-1

pragma warning (C# Reference)

pragma warning may be used to enable or disable certain warnings.

http://msdn.microsoft.com/en-us/library/441722ys(VS.80).aspx

Jay Bazuzi
  • 45,157
  • 15
  • 111
  • 168
-3

It seems to me the root problem is really a combination of your treating warnings as errors, when they are clearly not, and your apparent policy of permitting check-ins which violate this. As you say, you want to be able to continue working despite a warning. You've only mentioned a few warnings you want to be able to ignore, but what if someone else on the team caused any other type of warning, which would take you equally long to fix? Wouldn't you want to be able to ignore that as well?

The logical solution would be to either 1) Disallow checkins if the code doesn't compile (which means those who created the warnings will have to fix them, since in effect, they broke the build), or 2) treat warnings as warnings. Create two build configurations, one which treats warnings as errors, which can be run regularly to ensure that the code is warning-free, and another, which only treats them as warnings, and allows you to work even if someone else introduced a warning.

jalf
  • 243,077
  • 51
  • 345
  • 550
  • 1
    Using the selected answer, it's easy to add to the list of warnings treated as warnings. That works much better than either of your proposed solutions. Warnings clearly are not errors, but treating most warnings as errors means code will never be checked in with those warnings. – Neil Oct 06 '09 at 22:52