In general, there is no easy way to predict whether a method will be embedded. You should actually write a program and look at the machine code created for it. This is quite easy to do in a C program, you can ask the compiler to create a list of build code (for example, / FA for MSVC, -S for GCC).
More complicated in .NET due to jitter, exactly at the time the code was compiled. Technically, the optimizer source code is available from the CoreCLR project, but itβs very difficult to understand what it does, a lot of pretty impregnable C ++ code. You must use the "visual" in Visual Studio and use the debugger.
This takes a bit of preparation to make sure you get the actual optimized code, it usually disables the optimizer to make debugging easier. Switch to the Release configuration and use "Tools"> "Options"> "Debug"> "General"> check the box "Suppress JIT Optimization". If you need an optimal floating point code, then you always, always want a 64-bit code, so use Project> Properties> Build tab, untick "Prefer 32-bit".
And write a small test program to implement this method. It can be tricky; you can easily get the code at all. In this case itβs easy, Console.WriteLine () is a good way to make this method used, it cannot be optimized. So:
class Program { static void Main(string[] args) { var obj = new Example(); Console.WriteLine(obj.GetDiameter()); } } class Example { private float radius = 0.0f; public float GetDiameter() { return radius * 2.0f; } }
Set a breakpoint on Main () and press F5. Then use Debug> Windows> Disassembly to look at the machine code. On my machine with a Haswell kernel (supported by AVX) I get:
00007FFEB9D50480 sub rsp,28h ; setup stack frame 00007FFEB9D50484 mov rcx,7FFEB9C45A78h ; rcx = typeof(Example) 00007FFEB9D5048E call 00007FFF19362530 ; rax = new Example() 00007FFEB9D50493 vmovss xmm0,dword ptr [rax+8] ; xmm0 = Example.field 00007FFEB9D50499 vmulss xmm0,xmm0,dword ptr [7FFEB9D504B0h] ; xmm0 *= 2.0 00007FFEB9D504A2 call 00007FFF01647BB0 ; Console.WriteLine() 00007FFEB9D504A7 nop ; alignment 00007FFEB9D504A8 add rsp,28h ; tear down stack frame 00007FFEB9D504AC ret
I annotated the code to help sort this out, it may be cryptic if you have never looked at it before. But, without a doubt, you can say that the method was built-in. There is no CALL instruction; it was bound to two instructions (VMOVSS and VMULSS).
As expected. Accessibility does not play any role in decision making, it is a simple trick that does not change the logical operation of the program. This is important for the C # compiler at first, next to the verifier built into the jitter, but then disappears as a problem with the code generator and optimizer.
Just do the same for the abstract class. You will see that the method is not embedded, the indirect CALL instruction is required. Even if the method is completely empty. Some language compilers can turn virtual method calls into non-virtual calls when they know the type of object, but the C # compiler is not one of them. The jitter optimizer does not work either.
There are other reasons why the method will not be embedded, a moving target that is difficult to document. But roughly speaking, methods with too many MSIL, try / catch / throw, loop, CAS, some degenerate structural cases, the MarshalByRefObject base will not be included. Always look at the actual machine code.
The [MethodImpl (MethodImplOptions.AgressiveInlining)] attribute can cause the optimizer to revise the MSIL limit. MethodImplOptions.Noinlining helps turn off embedding, something you might want to do to get a better exception stack trace or slow down jitter because the assembly cannot be deployed.
Learn more about optimizations performed by the jitter optimizer in this post .