A constructor with an optional parameter violates the new () constraint

I have a class with this constructor:

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

and I want to use this class with the new() constraint, but I get this error:

A "currency" must be a non-abstract type with an open constructor without parameters in order to use it as a "T" parameter in a generic type or method ...

If I share the constructor, everything works fine:

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

why should i break the constructor?

+6
source share
2 answers

Because the constructor with the default parameter is not a constructor without parameters.

The default parameters are "populated" by the compiler at compile time. When you write:

 var foo = new Currency(); 

The compiler generates:

 var foo = new Currency(null); 

When the class compiles, does the compiler create a constructor that accepts this Guid? parameter Guid? , and also generates some metadata that acts "if the parameter is not specified at compile time, then supply null ." But for a type, a constructor without parameters is not created.

The new() constraint requires a typeless constructor to be defined for the type, and it will not accept a constructor with a single default parameter. Most likely, due to the fact that the runtime, which ultimately calls the constructor, does not understand the concept of default parameters.

+15
source

Although Jim has already answered your question, note that a more general approach might be to allow the delegate to be passed that will create your specific class, instead of forcing all your implementations to be parameterless.

those. instead of this:

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

You can pass an explicit delegate that will execute any custom instance creation logic:

 // 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) ); 

It also allows you to create a helper class and have both options:

 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); } } 
+5
source

All Articles