在DLL中使用default关键字

时间:2014-11-05 17:29:37

标签: c# mono default

在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编译第二个项目时,不会发生这种情况。

1 个答案:

答案 0 :(得分:5)

这似乎是单声道编译器3.2.3之前的错误(@usr在他们的初始评论中是完全正确的)。编译器将默认参数值作为属性插入到程序集元数据中(请参阅this answer)。我验证了ilspy的输出与ildasm一致,ildasm将default(T)编码为.param [1] = nullref。我怀疑约定是泛型default(T)编码为null,消费编译器应该知道如何使用它。它似乎与this issue有关,但是,基于日期,这个特定问题在报告之前已经修复了一段时间。