It seems to me that this discrepancy is fundamentally a conflict between the C# language specification (most recent non-draft specification, i.e. C# 5.0, linked, but other versions are essentially identical in this respect) and the Common Language Infrastructure specification.
Specifically, the language specification gives the triggers you've mentioned, but the CLI specification includes this description for types not marked with the BeforeFieldInit
flag (as is the case here):
The semantics of when and what triggers execution of such type initialization methods, is as follows:
…
4. If not marked BeforeFieldInit then that type’s initializer method is executed at (i.e.,
is triggered by):
a. first access to any static field of that type, or
b. first invocation of any static method of that type, or
c. first invocation of any instance or virtual method of that type if it is a value
type or
d. first invocation of any constructor for that type.
(my emphasis)
In other words, for the runtime, the rules are explicitly that invoking any instance method of a type will cause the static constructor (i.e. the "type initializer") to be invoked. That's exactly how your program is behaving.
The language in the C# specification has persisted so long, through earlier versions of the specification all the way through the latest released version of the language (technically a "draft" specification, but still prescriptive), it's difficult for me to think that this discrepancy is a simple oversight. It could be, of course (barring input from the language designers). But I think it's just as likely that the language designers decided to be minimally restrictive in spite of the CLI's rules (since in theory, the C# language could target other similar platforms, platforms that might not be as restrictive as the CLI), and just live with the difference.
After all, the CLI implementation of a C# program, following its rules instead of the C# rules, is unlikely to be problematic for anyone. It should be exceedingly rare, and arguably very poor design, for a program to actually rely on the static constructor not being called when a method that accesses no static members is itself called.