在DLL项目中使用default
关键字时,我遇到了一个非常奇怪的问题。在我的DLL项目(使用VS2013编译)中,我有以下类:
public class BaseClass<T>
{
public T value;
public bool enabled;
public BaseClass ( T value = default(T), bool enabled = true )
{
this.value = value;
this.enabled = enabled;
}
}
现在,如果我在DLL项目中使用它,它可以很好地工作。我可以创建从这个基类派生的类而不会出现问题。但是,只要我尝试在另一个项目中使用DLL(使用Mono 2.0.0编译),从基类派生值类型会导致编译器错误。这样:
public class ChildClass : BaseClass<int>
{
}
导致这个:
Assets / ChildClass.cs(8,14):错误CS1502:BaseClass的最佳重载方法匹配&lt; int&gt; .BaseClass(int,bool)'有一些无效的参数
Assets / ChildClass.cs(8,14):错误CS1503:参数
#1' cannot convert
null'表达式以输入“int”
但是,具有值类型的基类可以在没有问题的字段中使用:
public class OtherClass
{
public BaseClass<int> baseInt;
}
我使用ILSpy查看了DLL并注意到了这一点:
public class BaseClass<T>
{
public T value;
public bool enabled;
public BaseClass(T value = null, bool enabled = true)
{
this.value = value;
this.enabled = enabled;
}
}
请注意,构造函数中的default<T>
已替换为null
。这似乎是问题的原因,因为null将是值类型的无效值。
那么这里发生了什么?
编辑:正如在评论中发现的那样,当使用VS2013或更新版本的Mono编译第二个项目时,不会发生这种情况。
答案 0 :(得分:5)
这似乎是单声道编译器3.2.3之前的错误(@usr在他们的初始评论中是完全正确的)。编译器将默认参数值作为属性插入到程序集元数据中(请参阅this answer)。我验证了ilspy的输出与ildasm一致,ildasm将default(T)
编码为.param [1] = nullref
。我怀疑约定是泛型default(T)
编码为null,消费编译器应该知道如何使用它。它似乎与this issue有关,但是,基于日期,这个特定问题在报告之前已经修复了一段时间。