我在GitHub上浏览System.Linq.Expressions源代码,发现以下代码
public static NewExpression New(ConstructorInfo constructor, IEnumerable<Expression> arguments)
{
ContractUtils.RequiresNotNull(constructor, nameof(constructor));
ContractUtils.RequiresNotNull(constructor.DeclaringType, nameof(constructor));
// ...
}
我被第二个空检查弄糊涂了,所以去了MSDN。它对ConstructorInfo有如下说明。DeclaringType:
DeclaringType属性为声明该成员的类型检索对Type对象的引用。类型的成员要么由类型声明,要么从基类型继承,因此DeclaringType属性返回的type对象可能与用于获取当前MemberInfo对象的type对象不同。
如果获得MemberInfo对象的Type对象没有声明该成员,则DeclaringType属性将表示它的一个基类型。
如果MemberInfo对象是一个全局成员(也就是说,如果它是从Module中获得的)。GetMethods方法(它返回模块上的全局方法),返回的DeclaringType将为null。
因此,似乎DeclaringType对于MemberInfo (ConstructorInfo派生的类)可以为null。但我不确定它是否可以为null或不为ConstructorInfo。
对于我的问题:
ConstructorInfo。声明类型是否为空?为什么System.Linq.Expressions代码要检查它?
如果DeclaringType可以为null,能否举例说明?
如果DeclaringType可以为null,这是否意味着CLR支持全局构造函数?(我试着研究这个,但找不到任何东西)
ConstructorInfo.DeclaringType
的源代码:
public override Type DeclaringType
{
get
{
return m_reflectedTypeCache.IsGlobal ? null : m_declaringType;
}
}
我没有这个场景的具体例子,但是考虑到这是ConstructorInfo
类本身,对我来说似乎很清楚,它是专门写的,它的DeclaringType
属性可能返回null
。
我怀疑在c#代码中可能会发生这种情况,但是CLR支持各种各样的语言。对我来说,c++/CLI似乎是这种情况下最有可能的罪魁祸首,因为c++/CLI汇编最终会带有一堆样板文件和全局成员,但是VB。NET也做一些全局的东西。据推测,可以直接生成IL,这也会造成这种情况。