I have a piece of code which looks a little like this:
public TReturn SubRegion(TParam foo)
{
Contract.Requires(foo!= null);
Contract.Ensures(Contract.Result<TReturn>() != null);
if (!CheckStuff(foo))
foo.Blah();
return OtherStuff(foo);
}
CC is giving me a warning:
Warning 301 CodeContracts: Consider adding the postcondition Contract.Ensures(Contract.Result() != null); to provide extra-documentation to the library clients
Which is obviously completely redundant! I have several such redundant warnings and it's becoming a problem (real warnings getting buried in a torrent of redundant suggestions).
So I have two questions:
1) Am I missing something which means this is not a redundant recommendation? In which case what do I need to do to fix this warning?
2) Alternatively, if this is just a quirk of CCCheck and cannot be fixed how can I hide or suppress this warning?
N.b. Just in case you think my example is missing something important, the full code is the SubRegion method here.
Regarding 2: The documentation is pretty good, take a look at 6.6.10 Filtering Warning Messages:
To instruct the static contract checker not to emit a particular class
of warnings for a method (a type, an assembly), annotate the method
(the type, the assembly) with the attribute:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Contracts", warningFamily)]
where warningFamily is one of: Requires, Ensures, Invariant, NonNull,
ArrayCreation, ArrayLowerBound, ArrayUpperBound, DivByZero,
MinValueNegation.
If necessary, the static contract checker allows filtering a single
warning message (instead of an entire family) as well. To do so you
can annotate a method with the attribute
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Contracts", warningFamily-ILOffset-MethodILOffset)]
where warningFamily is as
above, and ILOffset and MethodILOffset are used by the static
contract checker to determine the program point the warning refers to.
The offsets can be obtained from the static contract checker by
providing the -outputwarnmasks switch in the "Custom Options" entry in
the VS pane. Check the Build Output Window for the necessary
information.
Related
I've started using nullable reference types in C# 8. So far, I'm loving the improvement except for one small thing.
I'm migrating an old code base, and it's filled with a lot of redundant or unreachable code, something like:
void Blah(SomeClass a) {
if (a == null) {
// this should be unreachable, since a is not nullable
}
}
Unfortunately, I don't see any warning settings that can flag this code for me! Was this an oversight by Microsoft, or am I missing something?
I also use ReSharper, but none of its warning settings appear to capture this either. Has anybody else found a solution to this?
Edit: I'm aware that technically this is still reachable because the nullability checks aren't bulletproof. That's not really the point. In a situation like this, where I declare a paramater as NOT nullable, it is a usually a mistake to check if it's null. In the rare event that null gets passed in as a non-nullable type, I'd prefer to see the NullReferenceException and track down the offending code that passed in null by mistake.
It's really important to note that not only are the nullability checks not bullet proof, but while they're designed to discourage callers from sending null references, they do nothing to prevent it. Code can still compile that sends a null to this method, and there isn't any runtime validation of the parameter values themselves.
If you’re certain that all callers will be using C# 8’s nullability context—e.g., this is an internal method—and you’re really diligent about resolving all warnings from Roslyn’s static flow analysis (e.g., you’ve configured your build server to treat them as errors) then you’re correct that these null checks are redundant.
As noted in the migration guide, however, any external code that isn’t using C# nullability context will be completely oblivious to this:
The new syntax doesn't provide runtime checking. External code might circumvent the compiler's flow analysis.
Given that, it’s generally considered a best practice to continue to provide guard clauses and other nullability checks in any public or protected members.
In fact, if you use Microsoft’s Code Analysis package—which I’d recommend—it will warn you to use a guard clause in this exact situation. They considered removing this for code in C# 8’s nullability context, but decided to maintain it due to the above concerns.
When you get these warnings from Code Analysis, you can wrap your code in a null check, as you've done here. But you can also throw an exception. In fact, you could throw another NullReferenceException—though that's definitely not recommended. In a case like this, you should instead throw an ArgumentNullException, and pass the name of the parameter to the constructor:
void Blah(SomeClass a) {
if (a == null) {
throw new ArgumentNullException(nameof(a));
}
…
}
This is much preferred over throwing a NullReferenceException at the source because it communicates to callers what they can do to avoid this scenario by explicitly naming the exact parameter (in this case) that was passed as a null. That's more useful than just getting a NullReferenceException—and, possibly a reference to your internal code—where the exception occurred.
Critically, this exception isn't meant to help you debug your code—that's what Code Analysis is doing for you. Instead, it's demonstrating that you've already identified the potential dereference of a null value, and you've accounted for it at the source.
Note: These guard clauses can add a lot of clutter to your code. My preference is to create a reusable internal utility that handles this via a single line. Alternatively, a single-line shorthand for the above code is:
void Blah(SomeClass a) {
_ = a?? throw new ArgumentNullException(nameof(a));
}
This is a really roundabout way of answering your original question, which is how to detect the presence of null checks made unnecessary by C#’s non-nullable reference types.
The short answer is that you can’t; at this point, Roselyn’s static flow analysis is focused on identifying the possibility of dereferencing null objects, not detecting potentially extraneous checks.
The long answer, though, as outlined above, is that you shouldn’t; until Microsoft adds runtime validation, or mandates the nullability context, those null checks continue to provide value.
Back in the days of C/C++, Microsoft had a #define, which allowed programmers to reference an unused parameter. The declaration, part of windef.h, is:
#define UNREFERENCED_PARAMETER(P) {(P)=(P);}
#define UNREFERENCED_LOCAL_VARIABLE(L) {(L)=(L);}
Whatever the exact name and syntax, the line had the effect of
Telling the compiler to not flag this unused parameter as a warning
The later stages of the compiler was smart enough to not include the line in the binary (or so I recall)
Visually tells the viewer that the unreferenced parameter was not an oversight.
Is there a similar syntax in C#?
Although it makes no difference for this question, but the DevExpress CodeRush Visual Studio add-in flags all unused parameters, even in event handlers, as a warning.
NOTE:
As I stated in my comment, I do not want to use pragma blocks. The purpose is to add a line of code that references the parameter for warning sake but adds none to trivial overhead, like what the windef.h header file macro did.
Maybe the discard _ is what you're looking for:
void Foo(string parameter)
{
_ = parameter;
}
Using the SuppressMessage attribute you can suppress warnings where ever you want:
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isChecked")]
[SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "fileIdentifier")]
static void FileNode(string name, bool isChecked)
{
string fileIdentifier = name;
string fileName = name;
string version = String.Empty;
}
This also gives the reader an explicit understanding that this is intended behavior.
More on the SuppressMessage attribute.
You can use the following syntax to disable and re-enable specific warnings. Surround the code that declares the unused/unreferenced paramter:
#pragma warning disable <warning-number>
// ... code that declares the unused parameter
#pragma warning restore <warning-number>
Where the <warning-number> above would be the warning number issued by the compiler that you wish to suppress. Presumably that would be C# warning number 219.
Using pragma statements only allow turning on or turning off compiler warnings. Since it is most likely you only want to affect the file you are working in, this will cause problems if someone later decides to disable the warning project wide. Every file compiled after the file with the pragma restore in it may report an unwanted warning.
Embedded developers will recognize this as the common problem of trying to enable and disable interrupts without knowing what the previous interrupt status was.
Here's a hack that you might use:
namespace YourComapany.Tools{
class CS
{
public static void UNREFERENCED_PARAMETER<T>(T t) {if(t == null) {T d=t;}
}
};
...
CS.UNREFERENCED_PARAMETER(whatever);
I am using T4 to generate some code. The code will be in a class called "MyClass.generated.cs" and typical output will look like this.
//<autogenerated/>
namespace MyNamespace
{
using System;
using System.CodeDom.Compiler;
[GeneratedCode("T4", "1.0.0.0")]
public partial class MyClass: SomeBaseClass
{
private SomeBaseClass myBackingField;
}
}
However, even though the class is decorated with the GeneratedCodeAttribute, I still get a Code Analysis warning as follows:
Field 'MyNamespace.MyClass.myBackingField' is never assigned to, and will always have its default value null
I have ensure that the Project Properties → Code Analysis → "Suppress results from generated code (managed only)" checkbox is checked.
Please note that I understand the meaning of the warning - I just want to know how to suppress it :)
Possible solutions
I could modify my generator to use Suppressions to suppress specific warnings, but this is extra work that I shouldn't have to do (as generated code should be ignored by Code Analysis).
Related Questions
Visual studio code analysis for generated files
EDIT with background context
The actual generated code is essentially a wrapper around SomeBaseClass. There are 100+ types in a namespace, and I want to change the behaviour of a subset of those. There are other warnings being generated as well - I just used this one as an example. Consider for example, if there is a property SomeBaseClass.MyObsoleteProperty, which is decorated with the ObsoleteAttribute. My code generater would still create a MyClass.MyObsoleteProperty which would raise a Code Analysis warning.
Another example would be where the SomeBaseClass (which is from a 3rd-party) would itself raise Code Analysis warnings if they had bothered to check for them (maybe the class is not CLS-compliant, for example). My wrapper will recreate any errors they have (and that would actually be the desired behaviour).
I figured it out - this is not a Code Analysis warning - it's a compiler warning.
Therefore, the only way to disable it is to modify the generator to enclose the class in pragma directives to suppress compiler warnings, e.g
#pragma warning disable warning-list
// Now generate some code
#pragma warning restore warning-list
WARNING
Note that this is a dangerous feature - compiler warnings are there for a reason! Try and limit your use of it to as small a section as possible.
More information can be found at
Suppressing "is never used" and "is never assigned to" warnings in C#
List of compiler warnings and errors here.
I think you mean
#pragma warning disable
// generated code
#pragma warning restore
the "warning-list" is a placeholder in MSDN documentation for something like "c0605,c0403,c3498" etc
Does anyone know how to add Code Contracts Ensures in ReSharper ExternalAnnotations? It's not there in the last v7.1.3 nor in the latest v8 EAP, and neither in any of the custom xmls floating around.
Specifically it should detect if a method does not return a null: Contract.Ensures(Contract.Result<T>() != null);
If you're attempting to simply appease the analysis engine, the simplest thing to use is [NotNull] in front of the method declaration. The Contract Annotations to which you posted a link above is a more powerful mechanism for defining relationships between input parameters and the return value, e.g., [ContactAnnotation("null => null")].
However, explicitly analyzing for a Contract.Ensures statement is an entirely different proposition, as no automatic analysis can be defined for this statement via [ContractAnnotation] or any other ReSharper annotation attribute.
Usually, if I use switch for enums in C#, I have to write something like that:
switch (e)
{
case E.Value1:
//...
break;
case E.Value2:
//...
break;
//...
default:
throw new NotImplementedException("...");
}
In C++ (for VS) I could enable warnings C4061 and C4062 for this switch, make them errors and have a compile-time check. In C# I have to move this check to runtime...
Does anyone know how in C# I can have this checked in compile time? Maybe there is a warning, disabled by default, which I missed, or some other way?
No, there isn't be a compile-time check - it's legitimate to have a switch/case which only handles some of the named values. It would have been possible to include it, but there are some issues.
Firstly, it's entirely valid (unfortunately) for an enum value not to have any of the "named" values:
enum Foo
{
Bar = 0,
Baz = 1
}
...
Foo nastyValue = (Foo) 50;
Given that any value is feasible within the switch/case, the compiler can't know that you didn't mean to try to handle an unnamed value.
Secondly, it wouldn't work well with Flags enums - the compiler doesn't really know which values are meant to be convenient combinations. It could infer that, but it would be a bit icky.
Thirdly, it's not always what you want - sometimes you really do only want to respond to a few cases. I wouldn't want to have to suppress warnings on a reasonably regular basis.
You can use Enum.IsDefined to check for this up front, but that's relatively inefficient.
I agree that all of this is a bit of a pain - enums are a bit of a nasty area when it comes to .NET :(
I understand that this is necroposting, but nothing really changed in this area inside of the compiler. So, I made Roslyn analyzer for switch statements.
You can download SwitchAnalyzer package.
This is Roslyn analyzer and it supports
Enums with operations | and & for them. So, you can check flags as well
(but not like single int value)
Interface implementations (pattern matching) in the current data context.
Pattern matching for classes is not implemented in version 0.4 yet (but I hope to implement it soon).
To use it, just add this package to your project, you will get warnings for all uncovered cases if you don't have default branch or if it throws exception. And of course, you can enable "Treat warnings as errors" option for your project for all or specific warnings. Feel free to contact me in case if you will find any bugs.