Let??™s start with a simple situation first, with a single type parameter??”we??™ll use
List
for the sake of convenience. The JIT creates different code for each value type
argument??”int, long, Guid, and the like??”that we use. However, it shares the native
code generated for all the closed types that use a reference type as the type argument,
such as string, Stream, and StringBuilder. It can do this because all references are the
same size (they are 4 bytes on a 32-bit CLR and 8 bytes on a 64-bit CLR, but within any
one CLR all references are the same size). An array of references will always be the same
size whatever the references happen to be. The space required on the stack for a reference
will always be the same. It can use the same register optimizations whatever type
is being used??”the List goes on.
Each of the types still has its own static fields as described in section 3.4.1, but the
code that is executed is reused. Of course, the JIT still does all of this lazily??”it won??™t
generate the code for List before it needs to, and it will cache that code for all
future uses of List. In theory, it??™s possible to share code for at least some value
types. The JIT would have to be careful, not just due to size but also for garbage collection
reasons??”it has to be able to quickly identify areas of a struct value that are live
references.
Pages:
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194