带有可选参数的构造函数违反new()约束

时间:2014-04-30 14:08:38

标签: c# generics constructor constraints

我有一个带有这个构造函数的类:

public Currency(Guid? vcurrencyUI = null)
    : base(vcurrencyUI)
{ }

我希望将此类与new()约束一起使用,但我收到此错误:

  

'Currency'必须是具有公共无参数构造函数的非抽象类型,才能在泛型类型或方法中将其用作参数'T'...

如果我拆分构造函数,一切正常:

public Currency(Guid? vcurrencyUI)
    : base(vcurrencyUI)
{ }

public Currency()
    : base()
{ }

为什么我需要拆分构造函数?

2 个答案:

答案 0 :(得分:15)

因为具有默认参数的构造函数不是无参数构造函数。

默认参数"填写"由编译器在编译时。当你写:

var foo = new Currency();

编译器生成:

var foo = new Currency(null);

编译类时,编译器会创建一个构造函数,该构造函数接受Guid?参数,并生成一些有效的元数据"如果参数在编译时未提供,然后提供null。"但是没有为该类型生成无参数构造函数。

new()约束要求为该类型定义无参数构造函数,并且它不会接受具有单个默认参数的构造函数。很可能是因为运行时最终不得不调用构造函数,因此不了解默认参数的概念。

答案 1 :(得分:5)

虽然Jim already answered是您的问题,但请注意,更通用的方法可能是允许传递委托,这将实例化您的具体类,而不是强制所有实现都是无参数的。

即。而不是这个:

public class Something<T> where T : new()
{
    public T CreateInstance()
    {
        return new T();
    }
}

您可以传递一个显式委托,它将执行任何自定义实例化逻辑:

// note that the constraint is now removed
public class Something<T>
{
    private readonly Func<T> _ctor;
    public Something(Func<T> ctor)
    {
        _ctor = ctor;
    }

    public T CreateInstance()
    {
        return _ctor();
    }
}

// and you can now pass arbitrary constructor logic as a delegate
var x = new Something<Currency>( () => new Currency(null) );

这也允许您创建一个帮助程序类,并且可以随时使用这两个选项:

public class Something
{
    // this allows you to use a parameterless ctor
    public static Something<T> Create<T>() where T : new()
    {
        return new Something<T>(() => new T());
    }

    // this allows you to specify a custom one
    public static Something<T> Create<T>(Func<T> ctor)
    {
        return new Something<T>(ctor);
    }
}