Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Compiler should give warning but doesn't?

Someone on my team tried fixing a 'variable not used' warning in an empty catch clause.

try { ... } catch (Exception ex) { }

-> gives a warning about ex not being used. So far, so good.

The fix was something like this:

try { ... } catch (Exception ex) { string s = ex.Message; }

Seeing this, I thought "Just great, so now the compiler will complain about s not being used."

But it doesn't! There are no warnings on that piece of code and I can't figure out why. Any ideas?

PS. I know catch-all clauses that mute exceptions are a bad thing, but that's a different topic. I also know the initial warning is better removed by doing something like this, that's not the point either.

try { ... } catch (Exception) { }

or

try { ... } catch { }
like image 989
Cristian Diaconescu Avatar asked Apr 29 '10 21:04

Cristian Diaconescu


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is C full form?

Full form of C is “COMPILE”.

What is C language basics?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.


2 Answers

In this case the compiler detects that s is written but not read, and deliberately suppresses the warning.

The reason is because C# is a garbage-collected language, believe it or not.

How do you figure that?

Well, consider the following.

You have a program which calls a method DoIt() that returns a string. You do not have the source code for DoIt(), but you wish to examine in the debugger what its return value is.

Now in your particular case you are using DoIt() for its side effects, not its return value. So you say

DoIt(); // discard the return value

Now you're debugging your program and you go to look at the return value of DoIt() and it's not there because by the time the debugger breaks after the call to DoIt(), the garbage collector might have already cleaned up the unused string.

And in fact the managed debugger has no facility for "look at the thing returned by the previous method call". The unmanaged C++ debugger has that feature because it can look at the EAX register where the discarded return value is still sitting, but you have no guarantee in managed code that the returned value is still alive if it was discarded.

Now, one might argue that this is a useful feature and that the debugger team should add a feature whereby returned values are kept alive if there's a debugger breakpoint immediately following a method execution. That would be a nice feature, but I'm the wrong person to ask for it; go ask the debugger team.

What is the poor C# developer to do? Make a local variable, store the result in the local variable, and then examine the local in the debugger. The debugger does ensure that locals are not garbage collected aggressively.

So you do that and then the compiler gives you a warning that you've got a local that is only written to and never read because the thing doing the reading is not part of the program, it's the developer sitting there watching the debugger. That is a very irritating user experience! Therefore we detect the situation where a non-constant value is being assigned to a local variable or field that is never read, and suppress that warning. If you change up your code so that instead it says string s = "hello"; then you'll start getting the warning because the compiler reasons, well, this can't possibly be someone working around the limitations of the debugger because the value is right there where it can be read by the developer already without the debugger.

That explains that one. There are numerous other cases where we suppress warnings about variables that are never read from; a detailed exegisis of all the compiler's policies for when we report warnings and when we do not would take me quite some time to write up, so I think I will leave it at that.

like image 86
Eric Lippert Avatar answered Sep 22 '22 08:09

Eric Lippert


The variable s is used... to hold a reference to ex.Message. If you had just string s; you would get the warning.

like image 35
Gary.Ray Avatar answered Sep 21 '22 08:09

Gary.Ray