Instance fields are created every time a type instance is created, and they belong to the type instance. Static fields, which are shared by all instances of the type, are created when the type is loaded. Some of the static fields (literal and mapped fields) are never allocated. The loader simply notes where the mapped fields reside and addresses these locations whenever the fields are to be addressed. And the literal fields are replaced with the constants at compile time.
A field signature contains no indication of whether the field is static or instance. But because the loader keeps separate books for instance fields and for two out of three kinds of static fields—not for literal fields—the kind of referenced field is easily discerned from the field’s token. When a field token is found in the IL stream, the JIT compiler does not have to dive into the metadata, retrieve the record, and check the field’s flags; by that time, all the fields have been accounted for and duly classified by the loader.
IL has two sets of instructions for field loading and storing. The instructions for instance fields are ldfld , ldflda , and stfld ; those for static fields are ldsfld , ldsflda , and stsfld . An attempt to use a static field instruction with an instance field would result in a JIT compilation failure. The inverse combination would work, but it requires loading the instance pointer on the stack, which is, of course, completely redundant for a static field.