用 Reflector 发现这个类 (System.Internal) 发现里面有这么三个静态方法:
CommonlyUsedGenericInstantiations_HACK
NullableHelper_HACK<T>
SZArrayHelper_HACK<T>

它们的名字很奇怪, 方法里的内容更奇怪, 比如 CommonlyUsedGenericInstantiations_HACK 里的代码是:
private static void CommonlyUsedGenericInstantiations_HACK()
{
    
new ArraySegment<byte>(new byte[1], 00);
    
new Dictionary<charobject>();
    
new Dictionary<short, IntPtr>();
    
new Dictionary<intbyte>();
    
new Dictionary<intint>();
    
new Dictionary<intobject>();
    
new Dictionary<IntPtr, short>();
    
new Dictionary<objectchar>();
    
new Dictionary<object, Guid>();
    
new Dictionary<objectint>();
    NullableHelper_HACK
<bool>();
    NullableHelper_HACK
<byte>();
    NullableHelper_HACK
<char>();
    NullableHelper_HACK
<DateTime>();
    NullableHelper_HACK
<decimal>();
    NullableHelper_HACK
<double>();
    NullableHelper_HACK
<Guid>();
    NullableHelper_HACK
<short>();
    NullableHelper_HACK
<int>();
    NullableHelper_HACK
<long>();
    NullableHelper_HACK
<float>();
    NullableHelper_HACK
<TimeSpan>();
    
new List<bool>();
    
new List<byte>();
    
new List<DateTime>();
    
new List<decimal>();
    
new List<double>();
    
new List<Guid>();
    
new List<short>();
    
new List<int>();
    
new List<long>();
    
new List<TimeSpan>();
    
new List<sbyte>();
    
new List<float>();
    
new List<ushort>();
    
new List<uint>();
    
new List<ulong>();
    
new List<KeyValuePair<objectobject>>();
    RuntimeType.RuntimeTypeCache.Prejitinit_HACK();
    
new CerArrayList<RuntimeMethodInfo>(0);
    
new CerArrayList<RuntimeConstructorInfo>(0);
    
new CerArrayList<RuntimePropertyInfo>(0);
    
new CerArrayList<RuntimeEventInfo>(0);
    
new CerArrayList<RuntimeFieldInfo>(0);
    
new CerArrayList<RuntimeType>(0);
    
new KeyValuePair<charushort>('\0'0);
    
new KeyValuePair<ushortdouble>(0double.MinValue);
    SZArrayHelper_HACK
<bool>(null);
    SZArrayHelper_HACK
<byte>(null);
    SZArrayHelper_HACK
<DateTime>(null);
    SZArrayHelper_HACK
<decimal>(null);
    SZArrayHelper_HACK
<double>(null);
    SZArrayHelper_HACK
<Guid>(null);
    SZArrayHelper_HACK
<short>(null);
    SZArrayHelper_HACK
<int>(null);
    SZArrayHelper_HACK
<long>(null);
    SZArrayHelper_HACK
<TimeSpan>(null);
    SZArrayHelper_HACK
<sbyte>(null);
    SZArrayHelper_HACK
<float>(null);
    SZArrayHelper_HACK
<ushort>(null);
    SZArrayHelper_HACK
<uint>(null);
    SZArrayHelper_HACK
<ulong>(null);
    SZArrayHelper_HACK
<CustomAttributeTypedArgument>(null);
    SZArrayHelper_HACK
<CustomAttributeNamedArgument>(null);
}

这是看上去完全没有意义的代码啊... 而且其中调用 SZArrayHelper_HACK<T> 的地方传进去的参数是 null, 必然会抛出异常的:
private static void SZArrayHelper_HACK<T>(SZArrayHelper oSZArrayHelper)
{
    oSZArrayHelper.get_Count
<T>();
    oSZArrayHelper.get_Item
<T>(0);
    oSZArrayHelper.GetEnumerator
<T>();
}


不解的我Google之, 只搜到一篇相关的文章, 作者觉得这和JIT的编译效率有关, 和我的猜想也差不多, 但是没有任何地方调用它的方法啊.. 何况调用它还有抛出异常..
该不会是VM调用了它?
于是我想到了传说中的 SSCLI(Shared Source CLI, 就是共享源代码的CLI实现, 涵盖了.Net Framework (CLR, BCL, Compiler 的核心源代码)) ...
找到 System.Internal 类的源文件, 里面赫然写道:
// ==++==
// 
//   
//    Copyright (c) 2006 Microsoft Corporation.  All rights reserved.
//   
//    The use and distribution terms for this software are contained in the file
//    named license.txt, which can be found in the root of this distribution.
//    By using this software in any fashion, you are agreeing to be bound by the
//    terms of this license.
//   
//    You must not remove this notice, or any other, from this software.
//   
// 
// ==--==
/*
============================================================
**
** This file exists to contain miscellaneous module-level attributes
** and other miscellaneous stuff.
**
**
** 
===========================================================
*/
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
using System.Reflection;


[assembly:DefaultDependencyAttribute(LoadHint.Always)]
// mscorlib would like to have its literal strings frozen if possible
[assembly: System.Runtime.CompilerServices.StringFreezingAttribute()]

namespace System
{
    
static class Internal
    {
        
// This method is purely an aid for NGen to statically deduce which
        
// instantiations to save in the ngen image.
        
// Otherwise, the JIT-compiler gets used, which is bad for working-set.
        
// Note that IBC can provide this information too.
        
// However, this helps in keeping the JIT-compiler out even for
        
// test scenarios which do not use IBC.
        
// This can be removed after V2, when we implement other schemes
        
// of keeping the JIT-compiler out for generic instantiations.

        
static void CommonlyUsedGenericInstantiations_HACK()
        {
            
// Make absolutely sure we include some of the most common 
            
// instantiations here in mscorlib's ngen image.
            
// Note that reference type instantiations are already included
            
// automatically for us.

            
new ArraySegment<byte>(new byte[1], 00);

            
new Dictionary<Char, Object>();

             ................

            SZArrayHelper_HACK<UInt64>(null);

            SZArrayHelper_HACK
<CustomAttributeTypedArgument>(null);
            SZArrayHelper_HACK
<CustomAttributeNamedArgument>(null);
        }

        
static T NullableHelper_HACK<T>() where T : struct
        {
            Nullable.Compare
<T>(nullnull);    
            Nullable.Equals
<T>(nullnull); 
            Nullable
<T> nullable = new Nullable<T>();
            
return nullable.GetValueOrDefault();
        }       

        
static void SZArrayHelper_HACK<T>(SZArrayHelper oSZArrayHelper)
        {
            
// Instantiate common methods for IList implementation on Array
            oSZArrayHelper.get_Count<T>();
            oSZArrayHelper.get_Item
<T>(0);
            oSZArrayHelper.GetEnumerator
<T>();
        }
    }
}

看完它的注释, 虽然不是太懂 (IBC是什么?), 但也大概有个答案了:
这个类存在的意义是为了让这些一般的泛型类型的 Native Code 能在 Native Image 中存在 (我们都知道安装.Net Framework的时候, 像 Mscorlib.dll 这样的程序集已经安装到了 GAC 中了), 避免了 JIT 在运行时进行编译 (生成泛型类型的 Native Code)而造成的效率损失.
注释中还提到, 下一个版本的 .Net CLR(4.0? 3.0? 谁知道呢..) 将不会有这个 Trick.. 开发人员将会使用另外一种泛型的实现方案.

关于 .Net 2.0 中的泛型在运行时是如何编译的, 可以参考 Introducing Generics in the CLR
Posted on 2007-04-14 23:28  Adrian H.  阅读(1952)  评论(3编辑  收藏  举报