Does the compiler discard empty methods? - c#

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

Related

Why cant we use IteratorStateMachineAttribute in C#?

I did a Go To Definition (F12) on a class I was trying to derive from and I noticed that one of the methods was marked with AsyncStateMachineAttribute. Which in turn inherits StateMachineAttribute. I was curious and decide to read up on this attribute and all its derivates on MSDN. That led me to this and I came across this statement:
You can't use IteratorStateMachineAttribute to test whether a method is an iterator method in C#.
Because that statement is made to stand out, there must be serious implications to it but there is no further explanation as to why that is so. Does anyone have insights in this regard?
I'm 99% sure it's historical. Basically, C# introduced iterator blocks in C# 2 - a long time before this attribute was introduced.
The equivalent async attribute was introduced at the same time as async methods in C#, so that was fine... but even though the C# compiler now applies IteratorStateMachineAttribute to iterator blocks:
It doesn't apply to libraries created with older versions of the compiler, so you wouldn't be able to rely on it there.
It can't apply to libraries targeting versions of .NET prior to 4.5. (I'm not sure what the VB compiler does here, to be honest. It may omit the attribute, or it may require you to be targeting a recent version of .NET in order to use iterator methods.)
I would say that the presence of an IteratorStateMachineAttribute on a method is a good indicator that it is an iterator method (although there's nothing to stop a mischievous developer applying it to other methods), but it's not a sufficient test due to older versions of the C# compiler.
The State Machine here is one that is automatically generated by the C# compiler. The C# compiler internally converts lots of advanced features (like closures, the yield keyword, and async) into simplified C# before continuing. Things like 'AsyncStateMachineAttribute' is one bit of evidence that something like this has occured. You might also be familiar with classes called, e.g., DisplayClass923084923'1, which are the classes C# generates to implement closures.
When you use 'yield', say, the C# compiler first produces a version of the code which doesn't use 'yield' but instead uses a state machine implementation. In principle, from this;
yield "A";
yield "B";
to
int _state = 0;
if (_state == 0) { state = 1; return "A"; }
if (_state == 1) { state = 2; return "B"; }
This means the C# compiler, later on, doesn't have to deal with 'yield' as such -- it's been reduced to integers and return statements. I think this is where the IteratorStateMachineAttribute is added -- to the simplified, ints-and-returns version of the class.
(I think Async works the same way, producing a simplified state machine as its simplification step, which is how you came to it in the documentation.)
However, ever since the earliest version of C#, you've had the foreach keyword, which works on any object that has a GetEnumerator method, and that enumerator has methods like MoveNext and Result.
So -- an iterator method might be produced in different ways. IteratorStateMachineAttribute is what's supplied by the compiler in some cases, but you shouldn't rely on it being there.
This is informing that you cannot apply this flag to a method because during the compilation it will inject some IL code that cannot be reliably added to methods.

Why can I not find a custom attribute on this MethodInfo

I have a method with the following signature
[Specification]
public void slide_serialization() {
From a point in my code I need to move up the stacktrace to find the closest method with the SpecificationAttribute (performance is not an issue here). I find this method but I cannot find any custom attributes on it.
I don't think I've ever seen this happen. What might be the reason?
This is a unit testing assembly with Optimization disabled in Build.
The code snippet is not much to go by. But the stack trace makes it pretty clear what happened. Note the <>c_DisplayClass5 type name in the trace. This is an auto-generated class, produced by the C# compiler when it rewrites your code to compile a lambda expression with a closure. The subject of this Q+A.
The slide_serialization() method was rewritten as well, now acquiring the unspeakable <slide_serialization>_b40 method name. Use of angle brackets is intentional, it ensures that the members in the auto-generated code can never collide with identifier names in your program.
And you discovered a restriction in the code rewriting logic in the compiler. It does not transfer [attributes] on the original code to the rewritten code. Whether Microsoft did not think it was important enough to invest the effort or they could not do this correctly for every possible code rewriting rule is unclear. I strongly suspect the latter, the limitation is pretty painful. Usually discovered with much chagrin by programmers that need [SuppressMessage] attribute to get through code analysis without warnings.
There is no simple workaround for this, you have to deal with the limitation.

How to get an attribute to act as [Conditional("DEBUG")]?

I have a C# program where some parts of code are generated using D-style mixins (i.e., the body of the method is compiled, executed, and results inserted into a class). The method is marked with [MixinAttribute] and, naturally, I don't want it to be compiled into the program. Is there some cheap way of preventing the method decorated with this attribute from being included in a build?
The only way is with compiler conditionals:
#if DEBUG
[MixinAttribute]
// method you don't want included
#endif
The problem with this approach is that you then create a member which will be unavailable in builds where DEBUG is not defined. You then have to mark all usages with the conditional, and I don't think this is what you want. It's not quite clear but I think what you are really asking is how you create dynamic call sites at build time, or, rather, at JIT time (which is what the ConditionalAttribute controls). If this is the case, you can't really do this easily in C# without using some kind of dynamic dispatch overriding (using some proxying library) or by using some post-processing tool like PostSharp to manipulate the compiler output.

Will the compiler only compile code that can get executed?

I have a class library and am using only part of it. Is there a need to delete what isn't being used in order to shrink the size of the created code (in release configuration)?
As far as I've seen, the compiler takes care of that, and removing the code doesn't change the EXE file size. Will this always be true? Removing all unneeded code would take very long, so I want to know if there's need for that.
More information: there are methods and classes in the class library that aren't called from the executing code, but are referenced by other parts of code in the class library (which themselves are never called).
No, the compiler includes the "dead" code as well. A simple reason for this is that it's not always possible to know exactly what code will and won't be executed. For example, even a private method that is never referenced could be called via reflection, and public methods could be referenced by external assemblies.
You can use a tool to help you find and remove unused methods (including ones only called by other unused methods). Try What tools and techniques do you use to find dead code? and Find unused code to get you started.
It all gets compiled. Regardless of whether it is called or not. The code may be called by an external library.
The only way to make the compiler ignore code is by using Compiler Preprocessor Directives. More about those here.
I doubt the compiler will remove anything. The fact is, the compiler can't tell what is used and what is not, as types can be instantiated and methods called by name, thanks to reflection.
Let's suppose there is a class library called Utility. You created a new project and added this class library to that project. Even if your EXE calls only 1-2 methods from the class library, it's never a good idea to delete the unreferenced code.
It would go against the principle of reusablity. Despite the fact that there would be some classes present in the library unreferenced from the EXE, it would not have any bad impact on performance or size of the program.
Determining all and only dead code is (if one makes the idealization that one has a "math world" like language) recursively undecidable, in most languages. (A few rare ones like the Blaise language are decidable.)
to the question of whether there is a "need to delete what isn't being used in order to shrink the size of the created code": i think this would only be useful to save network bandwidth. removing unused code is crucial in web applications to improve loading speeds etc.
if you're code is an exe or a library, the only reason i see to remove dead code, is to improve your code quality. so that someone looking at your code 2 years down the line won't scratch their heads wondering what it does.

C# Compiler optimization - Unused methods

Does C# compiler (in VS2008 or VS2010) remove unused methods while compiling ?
I assume that it may have a problem deciding if public methods will ever be used, so I guess it will compile all the public methods.
But what about private methods that are never used inside a class ?
EDIT:
Are there a set of rules about the compiler's optmization that are documented anywhere ?
Just checked in reflector with a release build. The compiler doesn't remove the unused private methods.
There are ways to use a method without the compiler knowledge, like with reflection. So the compiler doesn't try to guess. It just leaves the methods there.
The only private methods the compiler removes are partial methods without implementation.
For the C# compiler optimizations, look here (archive.org).
The compiler doesn't strip any method from the assembly, public or private. I could in fact cause weird issues with reflection, and prevent runtime calls to such methods.
There are a lot of frameworks (like the XAML parser) which enable you to call private methods without static bindings (think about OnClick="myFunction" in a XAML file) This markup will call the potentially private myFunction when the OnClick event is raised... But the compiler has no informations about such a behavior at compile time.
Dynamic code suffer from the same issue, IL generation too. And you can access private methods from any object when executing under full trust.
This optimization is effectively implemented at the JIT level, which is good because then it works for both public/private/whatever methods. If a method is never called (ignoring ngen, etc.), it never gets JITed. Now you might say that this is still a waste of space for metadata etc. but as others have pointed out, private isn't so private.
No they won't be removed. It may give you warning for that but won't do it itself.

Categories

Resources