While we're waiting for Rider to maybe/hopefully integrate this functionality, here is one option that is in some regards even better than Microsoft's offering: the combined decompilation, IL and native disassembly view of newer LINQPad versions. I use both Rider and LINQPad all the time and they complement each other nicely.
Here's how I just verified that the cost of abstraction for a readonly struct
that wraps an Int64
is indeed zero as I had hoped:
(click to enlarge if necessary)
The upper pane shows the source code with a nested for
loop which repeatedly calls a static method on BT.ERezeptId
and stuffs the result into an array.
The decompilation pane (left) shows that the compiler has effectively converted the for
loops into equivalent while
loops.
I have focussed the IL pane (middle) only on the inner loop because in IL the loop setup and the outer loop add a lot of lines that are all boring.
The native code pane (right) shows that the compiler has cut through quite a lot of fluff when it optimised the IL. It has effectively inlined/flattened calls that are several layers deep on the source code level, thus eliminating all abstraction cost. The code is just as efficient as if it were dealing with naked Int64
instead of a struct that wraps one.
This is most immediately apparent from the fact that the method called on the source code level is zufaellig()
whereas the method called in the native code is Zufallswert()
. In fact, the compiler only stopped inlining at that point because I ordered it to do so!
Here are the layers of abstraction onion that got eliminated (all of which resides in a referenced assembly, not in the current source file):
public readonly partial struct ERezeptId
{
private readonly long m_Wert;
public ERezeptId (Ungeprueft<long> ungeprueft)
{
m_Wert = ungeprueft.Wert;
}
// ...
public static ERezeptId zufaellig (Random rng)
{
return new ERezeptId(new Ungeprueft<long>(Zufallswert(rng)));
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static long Zufallswert (Random rng)
{
// ...
}
}
public readonly struct Ungeprueft<T>
{
public readonly T Wert;
public Ungeprueft (T wert)
{
Wert = wert;
}
}
NB: the Ungeprueft<>
thing (German for 'unchecked') is a standard template of mine that makes it explicit when parameter validation is bypassed intentionally.
Note: this answer doesn't show how to view the disassembly in Rider - which is what the OP asked - because that functionality is not yet available in Rider. However, LINQPad can be a useful thing to have for any user of Rider, or any .NET programmer for that matter. In fact, if push came to shove I could maybe - with lots of cussing and loss of productivity! - use another IDE instead of Rider but it would be impossible for me to work effectively without LINQPad ...