.NET Internals Cookbook Part 8 — C# gotchas

This is the eighth part of the .NET Internals Cookbook series. For your convenience you can find other parts in the table of contents in Part 0 – Table of contents

52. Can you have class in a class? Class in an interface? Interface in a class? Interface in an interface?

Yes. No. Yes. No.:

You can put class in a class and interface in a class. You can have neither class nor interface in an interface. That is because an interface is a special kind of type. It is defined in Partition I of the Ecma International/ISO standard as “a named group of methods, locations, and other contracts that shall be implemented by any object type that supports the interface contract of the same name.” So it is not a real type but just a named descriptor of methods (and properties, which are methods) exposed by the type. To check this out you can actually implement an interface without implementing it:

See that Baz gets a method which has the expected signature but it is not a method written explicitly to implement the interface.

What’s more, depending on the assembly the classes are compiled differently. If Bar and Baz are in the same assembly then the Bar::Method is compiled as virtual final! So this method is virtual even though it was not marked as such. But if those classes are in different assemblies then Bar::Method is not virtual but there is a virtual method in Baz which delegates the call to the method in the base class.

Why is it so? Interface call needs to be polymorphic so we need to have the virtual modifier.

53. How is switch compiled?

It depends on the compiler version, variable type, number of labels. See this in .NET 4.5, VS 2017, C# 7:

This is compiled to cascade of ifs and elses:

This:

is compiled to switch:

This:

is compiled to if else again:

However, this:

is compiled to code using hashes:

Also, older compilers could use dictionaries, as shown here.

54. What is __makeref? __refvalue? __reftype? __arglist?

Those are keywords unrecognized by ReSharper and used pretty rarely to do some memory tricks. For first three you can see Custom memory allocation in C#. For __arglist see this code:

Interestingly, call is compiled to:

55. How do you make union in C#?

You need to specify struct memory layout, as shown here:

Output:

56. Can x == x ever give false? What about x.Equals(x)?

Yes and no:

Output:

Funny thing is that dotNetFiddle shows warning in first line: Comparison made to the same variable; did you mean to compare something else?

NaN is never == to itself, this is specified by IEEE 754 standard. However, Equals contract says that anything must be equal to itself.

57. Can you have a global field in C#?

In C# no. You can do that in IL:

See that variable X is outside of any class or namespace.

58. Can you have try/catch/finally in method with yield/async?

See this:

And given errors:

You can have yield return in try if and only if you don’t have catch block. You cannot yield in finally.

You can have await anywhere. It was not always the case, in older C# version you couldn’t await in finally.