I have several user controls, that are subscribed to the event handler in another class.
I'm learning CodeContracts in C#, and I wonder, why does Static Analyzer allows writing code like this:
void MyUserControl_MouseEnter(object sender, MouseEventArgs e)
{
MyUserControl item = sender as MyUserControl;
item.DoSomething(); // I expect some warning here, because item can be null
sender.Equals(testObject); // This doesn't yield warning either
}
Here I have a potentially unsafe code, that can lead to null-reference exception.
I understand, that static analyzer probably cannot check, what will the actual type of sender be. But in case it cannot prove it, I expect some warning, like CodeContracts: Possibly calling a method on a null reference.
Or do I get some idea of contracts wrong? How can I get notified of errors like this?
UPD:
Yes, I did enable Implicit Non-Null Obligation as it was suggested in the answers, but I still don't get a warning from Static Analyzer. Also I tried to run Code Analysis with Microsoft All Rules rules set, also no warning. (But I'd prefer dealing with Code Contracts and perform some additional checks using Contract class, rather then with if-then-throw or something else)
You should enable "Implicit Non-Null obligations" in the static analyzer options (Project Options|Code Analysis).
"How can I get notified of errors like this?": Resharper will warn you in that case.
Code contracts will warn you that the object might be null if there is a "Requires" that the object be non-null. You're asking for an implicit "Requires" for an object dereference, which seems reasonable on the face of it, but which CC for whatever reason doesn't seem to provide.
The documentation at http://msdn.microsoft.com/en-us/library/dd264808.aspx says that it does enforce such an implicit contract. I'm looking into it further.
RedHat beat me to it. More detail: You should check the "Implicit Non-Null Obligations" box under "Static Checking" in the Code Contracts tab of your project properties.
I had a similar problem. I had to turn up the warning level slider on the same panel as the "Implicit Non-Null obligations" checkbox.
In properties page of your project on Code Analysis tab you can change Rules.
Related
Often I have the pieces of code that look like this:
private void OnChangeLanguageCommandExecuted(object obj)
{
pLngService.ChangeLanguage(newLcid);
}
In this case the ChangeLanguage(...) method returns a value, although that value (true for success, false for non-success) is not used. The problem is, I had no clue when looking at the code that this method was returning a value.
I did not write the method, nor have I control over it.
Therefore i'd like to globally enforce a policy where:
Each non-void returning method must be assigned a variable, e.g.
var unused = pLngService.ChangeLanguage(newLcid);
Or the discard operator should be used, to make it more explicit:
_ = pLngService.ChangeLanguage(newLcid);
I'm of course open to other suggestions, the main goal here is to make it more verbose that both a method is returning a value and that i'm choosing to discard it.
I was hoping there'd be a rule for visual studio or Resharper where i could enfore this policy by generating compiler warnings. I won't like to make this a compiler error, that seems to rigorous. I did some quick looking around but i did not find anything oob but i feel like im overlooking something.
I'm using projects in vs2017 (net4) and vs2019 (net8/netcore3.0) so something that would work in either of those setups would be great.
EDIT:
I found out, literally whilst writing a roslyn code analyzer, that apperently you can configure this with https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0058
The code fixes were exactly what I was looking for:
// Original code:
System.Convert.ToInt32("35");
// After code fix for IDE0058:
// csharp_style_unused_value_expression_statement_preference = discard_variable
_ = System.Convert.ToInt32("35");
// csharp_style_unused_value_expression_statement_preference = unused_local_variable
var unused = Convert.ToInt32("35");
There is the following rule:
csharp_style_unused_value_expression_statement_preference
With options:
Option values discard_variable - Prefer to assign an unused expression to a discard
unused_local_variable - Prefer to assign an unused expression to a local variable that is never used
For future readers, please refer to the code rule IDE0058:
https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0058
Also see: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-options?view=vs-2019 on how to configure editor rules.
Which should provide what you need. If thats not available, or the rule is buggy in your particular version of VS you can also take a look at this quick roslyn analyzer i made on a saturday morning:
https://github.com/sommmen/DiscardReturnValueAnalyzer/tree/master
She works but there are still some things i'm not happy with, like the actual analysis messages. But since IDE0059 should already cover this use case I'm not putting more effort into this. If you need this for some reason, feel free to create an issue and I might take a look.
Also the repo is not published or something so you'd have to clone and build it yourself.
P.s. Roslyn analyzers are pretty dope once you get the hang of them.
Multiple enumeration of the same enumerable is something that has been a performance problem for us, so we try to stomp those warnings in the code. But there is a generic extension function that we have for throwing null parameter exceptions that generates a lot of these warnings. Its signature looks like this:
public static void VerifyArgumentIsNotNull<T>(this T value, string valueName) where T : class
All it does is check for null and throw a nicely formatted and localized (for whichever human language is in play at the time) exception.
When this function is used on an IEnumerable parameter, it makes the code analysis warn about a possible multiple iteration of the IEnumerable because the analyzer has no idea what that function does.
I would like to put some tag on this function that says, "Yes, this takes the enumerable as an input, but it does not iterate it and therefore should not be counted as a possible iteration by callers." Is there any such tag? I've searched the Internet to no avail.
Yes, what you're asking is very much possible, but requires a little work. ReSharper uses Code Annotations to add hints to its analysis engine and make more sense of the code it has to work with. I recently recorded a webinar with JetBrains called ReSharper Secrets, where I go into much greater detail about what Annotations are and how to use them. You should watch it!
There's an annotation attribute, [NoEnumeration] that does exactly what you ask - specifies that the given IEnumerable argument is not enumerated, however it's not included in the default Code Annotation Attributes, however it is defined in the JetBrains.Annotations.dll assembly.
So after this introduction, here's what you need to do:
(if you haven't already,) go to ReSharper Options, then Code Inspection → Code Annotations, and press the Copy default implementation to clipboard button
Create a file in any of your (shared) projects called Annotations.cs (or any other name)
Paste the code from the clipboard, completely replacing anything that was previously in Annotations.cs
Add the following definition at the end of the file:
Code:
/// <summary>
/// Indicates that IEnumarable, passed as parameter, is not enumerated.
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class NoEnumerationAttribute : Attribute
{
}
After you done this, all that's left to do is place the [NoEnumeration] attribute on the value argument, like this:
public static void VerifyArgumentIsNotNull<T>([NoEnumeration] this T value, string valueName) where T : class
{
....
}
And that's it! The warning will disappear!
Bonus:
There are 3 additional attributes you can use to decorate this method to make it even more useful: [NotNull], [ContractAnnotation] and [InvokerParameterName]. I recently describe what they do (and a short demo) in this issue for a similar API called LiteGuard.
Annotations are fun :)
Since VerifyArgumentIsNotNull is generic, but does nothing type specific, it can take an object:
public static void VerifyArgumentIsNotNull(this object #object, string argumentName) { ... }
Resharper (9.11.) assumes that the called method does not cast #object back to an IEnumerable, and thus there is no warning.
Note the lack of the class constraint means the compiler may not warn if you accidentally pass a value type to VerifyArgumentIsNotNull, but Resharper will warn that a value type can never be null.
This approach has the additional advantage of saving the JIT from creating an instance (closed generic) method for every type that VerifyArgumentIsNotNull is called with; a micro-optimization to be sure, but a rare example where a generic may not be preferable to an old-school object.
One possible drawback to the above: I have seen similar implementations where VerifyArgumentIsNotNull returns "value". In this case a return value of type T is needed to avoid an explicit cast. (IMO this syntax is ugly. So it is not a drawback for me.)
Two other editorial comments:
1. A method name I have seen: ThrowIfNull is more concise, and "Throw" is more explicit than "Verify"
2. I no longer use methods for this, because without an annotation on VerifyArgumentIsNotNull Resharper must assume the argument could still be null. I find it much simpler to let R#, insert a 1-line if + throw when I add the NotNullAttribute.
This approach does not work for the broader case where you want to ensure that a method is called with an enumerable. In this case Igal Tabachnik's additions to Annotations are great.
Assuming you are using Visual Studio 2013/2012 (I'm only aware of this feature in 2013 though) in the code analysis window you should be able to right click the message navigate to Suppress Message > In Source File or In Suppression File
Alternatively you can achieve the same effect by clicking the action drop down of the message in the Code Analysis window.
Say I have two methods, one calls the other. The second method has code that will generate a compile time error. Since it's not called, why does the compiler still bother to process it?
void method1()
{
var i = 1;
//method2();
}
void method2()
{
int i = "2";
}
You can't be sure that someone else won't call that method at runtime using reflection. Your code MUST compile or it's not valid code - if it's never used... comment it out!
To expand on this:
Basically at compile time you are strongly typed - .NET will type check everything to ensure that what you are trying to do is legal, however, you can still throw exceptions at run time due to null references, bad casts etc etc.
Reflection is a component of the .NET framework that allows a developer to inspect the properties/fields/methods etc of an assemblies types via the assembly metadata
Reflection allows runtime type discovery and inspection of these types, it also allows invocation of methods/properties and modification of fields etc. (You can even create new generic types at runtime or completely new types altogether).
In other words, you can't guarantee that code you think won't be called, isn't called somewhere else at some point. For reflection to be possible, every bit of code needs to be valid and compilable
Whether that code will succeed at runtime is another story - but that's why we have exception handling.
And then what if somebody else uses your compiled code later on and decides to use it?
Even with private methods Reflection can complicate matters.
If you don't use it, lose it. (or at least comment it out)
In Perl I can say
use warnings;
warn "Non-fatal error condition, printed to stderr.";
What is the equivalent of this in C# ASP.NET? Specifically what I'm looking for is something so that other members of my team can know when they're still using a deprecated routine. It should show up at run time when the code path is actually hit, not at compile time (otherwise they'd get warnings about code sitting at a compatibility layer which ought to never run anyway.)
My best option so far is to use Trace, which feels like a bad hack.
Use ObsoleteAttribute. Decorate it over any method you want to mark as deprecated. They'll get a warning in their errors window, but the app will still compile.
public class Thing
{
[Obsolete]
public void OldMethod() { Console.WriteLine("I'm Old"); }
}
EDIT: I hadn't seen the bit in the question saying you wanted it at execution time.
The problem about writing out data execution time is that you need to know where to write it. What logging does your application use in general? Use the same form of logging as that, basically.
I would still favour the compile-time option listed below, however - you can turn off specific warnings in the compatibility layer using #pragma warn disable/restore, but it'll make it a lot easier to spot the problems than hoping someone reads a log file...
Old answer
Use the [Obsolete] attribute on any type or member. You can decide whether this should end up being a warning or an error. For example:
using System;
class Test
{
static void Main()
{
OldMethod();
BadMethod();
}
[Obsolete("Use something else instead")]
static void OldMethod() {}
[Obsolete("This would destroy your machine!", true)]
static void BadMethod() {}
}
Compiling this gives:
Test.cs(7,9): warning CS0618:
'Test.OldMethod()' is obsolete: 'Use
something else instead'
Test.cs(8,9):
error CS0619: 'Test.BadMethod()' is
obsolete: 'This would destroy your
machine!'
Ideally, the message should explain what the effects of continuing to use the method would be, and the suggested alternative.
You can use Trace.TraceWarning for run-time obsolete method usage detection, BUT you should really rethink your design and use ObsoleteAttribute and compile-time detection.
Run-time detection of such errors should be the last resort.
If your compatibility layer is auto-generated code, you can check for ObsoleteAttribute when generating the shims and mark such shims also [Obsolete]
If your compatibility layer uses reflection, it can check for ObsoleteAttribute and emit the warnings.
If your compatiblity layer is hand-coded you can write a tool that automatically inspects the IL in your compatibility layer and marks compatibility-layer methods [Obsolete] based on which methods they call.
In each case it would be best if all obsolete methods were actually marked with [Obsolete] so new code will not call them.
If your compatibility layer includes shims that call obsolete methods and these are also marked [Obsolete] you can safely compile it using this:
#pragma warning disable 618
This will hide the obsolete warnings when compiling the compatibility layer. Since your compatibility layer methods are also marked [Obsolete] you will get warnings at the correct locations.
FYI there is a #warning directive that can be used for run time warning generation; however, the [Obsolete] attribute sound much more like what you need.
There is no equivalent to warn's __WARN__ handling, but the printing to STDERR can be accomplished with a simple Console.Error.WriteLine() call.
That said, what you're really trying to do is mark something obsolete or deprecated, and others have shown you how to do that. Use that method rather than inserting warn calls into your function.
I think the Trace class is your best bet. Depending on how you intrusive you want to be you can use different trace levels or even a Fail statement (which brings up the nasty assert dialog).
private void SomeOldMethod()
{
Trace.Fail("You shouldn't call this method"); // <-- this will bring up an assert dialog
Trace.TraceWarning("You shouldn't call this method");
Trace.TraceError("You shouldn't call this method");
}
the way to flag a method as deprecated in c# is to use the obsolete attribute, this is overloaded to take a message to output (on intellisense) and a bool as to whether it should allow compile or not. I am not 100% convinced this matches what you want though, I am unfamiliar with perl
[Obsolete("A message",false)]
Imagine someone coding the following:
string s = "SomeString";
s.ToUpper();
We all know that in the example above, the call to the “ToUpper()” method is meaningless because the returned string is not handled at all. But yet, many people make that mistake and spend time trying to troubleshoot what the problem is by asking themselves “Why aren’t the characters on my ‘s’ variable capitalized”????
So wouldn’t it be great if there was an attribute that could be applied to the “ToUpper()” method that would yield a compiler error if the return object is not handled? Something like the following:
[MustHandleReturnValueAttribute]
public string ToUpper()
{
…
}
If order for this code to compile correctly the user would have to handle the return value like this:
string s = "SomeString";
string uppers = s.ToUpper();
I think this would make it crystal clear that you must handle the return value otherwise there is no point on calling that function.
In the case of the string example this may not be a big deal but I can think of other more valid reasons why this would come in handy.
What do you guys think?
Thanks.
Does one call a method for its side-effects, for its return value, or for both? "Pure" functions (which have no effects and only serve to compute a return value) would be good to annotate as such, both to eliminate the type of error you describe, as well as to enable some potential optimizations/analyses. Maybe in another 5 years we'll see this happen.
(Note that the F# compiler will warn any time you implicitly ignore a return value. The 'ignore' function can be used when you want to explicitly ignore it.)
If you have Resharper it will highlight things like this for you. Cant recommend resharper highly enough, it has lots of useful IDE additions especially around refactoring.
http://www.jetbrains.com/resharper/
I am not sure that I like this. I have called many a method that returns a value that I choose not to capture. Adding some type of default (the compiler generates a warning when a return value is not handled) just seems wrong to me.
I do agree that something along the suggested lines might help out new programmers but adding an attribute at this point in the game will only affect a very small number of methods relative the the large existing body. That same junior programmer will never get their head around the issue when most of their unhandled return values are not flagged by the compiler.
Might have been nice way back when but the horses are out of the barn.
I'd actually prefer a way to flag a struct or class as [Immutable], and have this handled automatically (with a warning) for methods called without using their return values on immutable objects. This could also protect the object by the compiler from changes after creation.
If the object is truly an immutable object, there really would be no way to handle it. It also could potentially be used by compilers to catch other common mistakes.
Tagging the method itself seems less useful to me, though. I agree with most of the other comments regarding that. If the object is mutable, calling a method could have other side-effects, so the above code could be perfectly valid.
I'm having flashbacks to putting (void) casts on all printf() calls because I couldn't get Lint to shut up about the return value being ignored.
That said, it seems like this functionality should be in some code checker tool rather than the compiler itself.
At least a compiler-warning would be helpful. Perhaps they add something similar for C# 4.0 (Design-By-Contract).
This doesn't warrant for a warning or pragma. There are too many places where it is intended to discard the result, and I'd be quite annoyed getting a warning/error from the compiler just because the method was decorated with some dodge attribute.
This kind of 'warning' should be annotated in the IDE's Editor, like a small icon on the gutter "Warning: Discarding return value" or similar.