First, what is it? When you make a method call, there is a lot of work that happens to make it happen -- the registers and parameters get written to the stack just before the function call, then the parameters get read from the stack inside the function and read again to restore the registers as the callee returns results to the caller. While on today’s hardware, this all adds up to a tiny amount of total execution, it adds up… especially when using properties.
To optimize this, compilers may choose to “inline” the method -- that is, to replace the method call with the method’s IL code. In other words, inlining takes the callee's IL code and inserts it into the caller's IL code effectively removing the method call.
Inlining reduces the direct cost of calls and also creates new opportunities for further optimizations on inlined code. It does, however, increase the size of the IL code. Too much inlining might cause code bloat, which might cause a lot of page faults (i.e. the system might spend a lot of time going out to disk to fetch the next chunk of code), which, in turn, will slow down performance.
If you function is not virtual and is small in size (normally 32 bytes of IL code or less), and there is no branching (i.e. no “if” statements), and you also don’t have local variables or exception handlers, then your function will likely be inlined by the compiler.
What that means is that your method will no longer appear in the current call stack; i.e. within the body of the inlined method’s code the System.Diagnostics.StackTrace will point to the caller, not the called method… Now, since inlining never occurs if you are running under a debugger, it’s normally not a problem. However, if you want to guarantee that inlining does not occur, mark your method with the following attribute: [MethodImpl(MethodImplOptions.NoInlining)].