Method invocation is skipped in C#? - c#

I have this simple code :
void Application_BeginRequest(object sender, EventArgs e)
{
Trace.Write("Exception Handling", "......");
}
However re-sharper scream (no-error only suggest) about :
Method invocation is skipped. Compiler will not generate method
invocation because the method is conditional, or it is a partial
method without implementation
I'm not able to see this line in the Trace output.
however - other traces - I do see.
Why is that ?
(p.s. The page (which is under web Site project) has trace="true").

Be sure that the TRACE constant is defined in your project settings for your current build configuration.
UPDATE
Since it's a website project, you could put
#define TRACE
at the top of Global.asax.cs so that the trace symbol is defined.

To quote the JetBrains wiki (which may* be linked to from the ReSharper menu under 'Why is ReSharper suggesting this'):
While coding, you may encounter warnings regarding methods whose
invocations will not be generated by the compiler. Why would that be?
Typical cases are conditional methods that will not be compiled (e.g.,
it’s marked with [ReSharperInt:Conditional("DEBUG")] and you’re in
RELEASE mode). Another reason why a method may be skipped is that,
at some point, its body has been declared as partial and the
implementation wasn’t provided.
Given that this is on a method of Trace, I'd suggest the first of these typical cases is the one that applies.
* I haven't got v7 yet

Related

How to emit compiler errors for unfinished features in Release Mode for .NET code?

Being inspired by this article I asked myself how can I emit compiler errors or , at least stop the build, if a feature is not implemented.
The only quick solution I came up with, is by creating a custom attribute:
public class NoReleaseAttribute : System.Attribute
{
public NoReleaseAttribute()
{
#if RELEASE
.
#endif
}
}
The idea is to have a syntactic error somewhere, but only for Release. I used an attribute because the IDE will help me find quickly the references to the attribute, and thus all places that I marked as needed to be completed or fixed before going in production.
I don't like this solution because I want one to emit a compiler error in each place that needs attention, not a single global error elsewhere.
Perhaps there is a more fitted solution.
You may use #error directive in your code, it will cause an error at compile-time.
Example usage:
static void Main(string[] args)
{
DoSomeStuff();
}
#error Needs to be implemented
static void DoSomeStuff(){
//This needs some work
}
There are no more fitted solution. You can use for your goal:
a) ObsoleteAttribute (may not fit your goal)
b) throw NotImplementedException in every place that you need to:
#if RELEASE
throw new NotImplementedException();
#endif
c) Wrap throwing NotImplementedException with attribute as you described us.
Basically it is unnecessary to add code that will not be used anywhere - Visual Studio even marking this code with 0 usages and it will not be included in CIL. So you have to question yourself - do i really need useless code exist in our project? It is better to track unreleased features in tracking systems like YouTrack or something, than to search them in your code.
I would suggest using a build step that checks the code for TODO-comments and generates warnings for them. A quick google suggest the Warn About TODOs extension might do just that, but it is not something I have used. You should also configure your build to fail on most warnings. A possible risk here is that people will just avoid using todo-comments, since they will fail the build.
But needing such a check suggest you do not have sufficient testing of your code. I find it a good practice to at least do some level of testing before committing any code, and just about any testing should reveal if entire components are not implemented. Reviewing your own code before committing is another practice that could be useful.
Automated unit testing can be a great way to deal with things like this. If you write unit tests for all your components the tests should find things like this, especially if you throw NotImplementedException in placeholders. This might require you to write your tests before the components, but there are certainly arguments for such a development approach.
The next line of defense should be code review. Even a quick review should find methods that are not implemented.
The final line of defense should be independent testing. If someone else tests the new features against the specification, any significant missing functionality should be found.

Debugger StepInto auto-generated code and JMC issue

I'm making a managed .NET debugger using MDBG sample.
Currently I'm struggling with StepInto behavior, while StepOut and StepOver seems to work.
To achieve Just-My-Code stepping I'm calling SetJMCStatus on modules load. That works fine and allow me to debug just my code.
But since I'm setting entire module as JMC, some auto-generated code comes into play and ruin stepping-into. An example of such code could be auto-property.
Since debugger is executing Il instructions, with step-into I'm getting inside auto-generated get_propertyName and set_propertyName method, which are marked as my code, because they are part of my module.
To distinguish such auto-generated code from my code I can use presence of debugging symbols, that are missing in case of auto-generated code. And then I could simply mark method as not my code to skip it during stepping.
The problem is I don't know which methods are auto-generated before I'm getting inside during stepping. When I stepped inside a method that has no debugging symbols I can mark it as not my code, but it's too late - debugger stopped where it supposed not to stop.
Theoretically I could iterate over my module methods using IMetadataImport and set their JMCStatus when debugger starts, but it seems quite expensive:
foreach (var methodToken in mdbgModule.Importer.EnumerateAllMethodTokens()) {
var func = mdbgModule.GetFunction(methodToken);
if (func.SymMethod == null)
func.CorFunction.JMCStatus = false;
}
If only I would know what function is going to be executed next, then I would be able to set it's status and prevent stepping inside auto-generated code for the first time.
I'm sticking with MDBG approach for stepping, not changing anything, just calling SetJMCStatus where it's needed, so I'm not sure if it makes sense to provide any code... If so, I'll edit the question, just add a comment!
Any suggestion on topic is greatly appreciated!
Regards,
Mike Stall hinted at one option, you could set JMC for the entire module and then when the debugger stepper breaks, check to see if the method is debuggable, if not then disable it's JMC status and rerun the stepper. (I'm not sure if this will result in a change in behaviour if the resuming stepper would need to step out before stepping in again.)
You could probably improve things by only setting JMC for modules that have a pdb available and by disabling JMC for classes/methods with [DebuggerNonUserCode] applied (and perhaps [DebuggerHidden] too). But rather than enumerating all the classes/methods and checking if they have the attribute, enumerate the custom attributes and work back (IMetaDataImport::EnumCustomAttributes with tkType set but not tk, then use IMetaDataImport::GetCustomAttributeProps to get the thing its applied to).
You might be able to do something similar with the [CompilerGenerated] attribute if its applied at the method level, but will get false positives when applied at the class level (the compiler applies it to state machines for iterators and async methods, but both will likely have non-generated code too).

Does the compiler discard empty methods?

Would C# compiler optimize empty void methods away?
Something like
private void DoNothing()
{
}
As essentially, no code is run aside from adding DoNothing to the call stack and removing it again, wouldn't it be better to optimize this call away?
Would C# compiler optimize empty void methods away?
No. They could still be accessed via reflection, so it's important that the method itself stays.
Any call sites are likely to include the call as well - but the JIT may optimize them away. It's in a much better position to do so. It's basically a special case of inlining, where the inlined code is empty.
Note that if you call it on another object:
foo.DoNothing();
that's not a no-op, because it will check that foo is non-null.
If you want you could intercept the post build event for every project and run an IL inspecting tool that will reflect your generated dll, inspect every methodinfo in your type and request it's IL looking for empty IL patterns like only NoOp IL instructions, and remove the unwanted methods.
For example:
var ilBytes = SomeMethodInfo.GetMethodBody().GetILAsByteArray();
A good obfuscation tool will "prune" methods in this way. preemptive.com/products/dotfuscator/features#pruning – weston 5 mins ago
You could use the tool externally of visual studio to find empty methods and remove them from the file they are defined or used in.
Never. Compiler doesn't has to do with what's empty or not written. Its just what you write, you get in your MSIL. you can check it here in ILDASM

Monitoring changes of a private field in an external assembly without source

I want to monitor (or place a breakpoint on) each change of a static field which is member of an internal class which resides in an external assembly for which I don't have code:
Assembly: PresentationCore.dll
Class : MS.Internal.MemoryPressure
Field : private static long _totalMemory
Ideally I should be able to see the stacktraces which trigger the changes.
Is this possible with VS and if yes then how do I have to setup VS in order to do this? Or will I need some external profiling tool?
You cannot set a breakpoint on a field. You are in luck, there's only one method that modifies the value, called AddToTotal. Debug + New Breakpoint + Break At Function. Type "MS.Internal.MemoryPressure.AddToTotal" and untick the "Use IntelliSense" option. The debugger will break as soon as the method is called, typically when the code creates a bitmap. You will only have machine code to look at.
As soon as it breaks, you can add a watch for MS.Internal.MemoryPressure._totalMemory. Adjust the breakpoint in the disassembly so it breaks past the field assignment.
Since PresentationCore is part of .Net you can debug the framework source
Take a look at this question
what about this:
http://ayende.com/blog/4106/nhibernate-inotifypropertychanged
Both RedGate Reflector as well as JetBrains Resharper can help you do it. They both decompile the assembly and generate the C# source code after which they allow you to work with it as if it were yours including placing breakpoints, watching the stack, etc.
I started with reflector, but now (starting from v.6) I switched to resharper it seems at this point to be more robust. Resharper has a 30 days trial, reflector used to be free I am not sure what it is now

Debug vs Trace in C#

As I understand statements like Debug.WriteLine() will not stay in the code in the Release build. On the other hand Trace.WriteLine() will stay in the code in the Release build.
What is controling this behaviour? Does the C# compiler ignores everything from the System.Diagnostics.Debug class when the DEBUG is defined?
I am just trying to understand the internals of C# and just curious.
These methods use the ConditionalAttribute to designate when they should be included.
When DEBUG is specified as a #define, via the command line or the system environment (set DEBUG = 1 in the shell), a method marked with [Conditional("DEBUG")] will be included by the compiler. When DEBUG is not included, those methods and any calls to them will be omitted. You can use this mechanism yourself to include methods under certain circumstances and it is also used to control the Trace calls like Trace.WriteLine (this uses the TRACE define).
This is due to ConditionalAttribute; the compiler ignores calls to methods marked as conditional unless that symbol is defined.
You can have your own:
[Conditional("BLUE")]
void Bar() {...}
which will only be called when BLUE is defined.
Note that there are some restrictions, to make "definite assignment" work:
no return value
no out parameters
(the same restrictions apply to partial methods for similar reasons)

Categories

Resources