The very-well known constraint in generic types is new(), it is possible to add parameters like (args,args,...) to force the compiler to check that the class contains a particular constructor?
The block shows you the case.
public class FooType
{
public FooType(int arg1)
{
}
}
public sealed class FooTypeChildA : FooType
{
public FooTypeChildA(int a) : base(a)
{
}
}
public sealed class FooTypeChildB : FooType
{
public FooTypeChildB() : base(0)
{
}
}
//public class FooConstraint<T> where T : FooType , new() // SUCCESS
//public class FooConstraint<T> where T : FooType , new(int) // ERROR
public class FooConstraint<T> where T : FooType // usually the constraint is "new()", but I need something like this: new(int) that the compiler verify the CHECK_1
{
}
public sealed class Passed : FooConstraint<FooTypeChildA> //[CHECK_1] Pass the constraint.
{
}
public sealed class NotPassed : FooConstraint<FooTypeChildB> //[CHECK_1] Not Pass the constraint.
{
}
This is instruction shows a possible syntax exception, new(int arg1)
Is not important the way that the generic instance invokes the constructor because a basic reflection solves the problem at run-time, but the idea is to force a Compiler error.
ATTEMPT#1 - This is not possible; because Interfaces must not specify constructors.
public interface IFoo
{
IFoo(int a); // Error here CS0526
}
ATTEMPT#2 - The original question was closed because the moderator was focused in solve the problem in runtime level instead of compilation-time level.
This Question is not duplicated in this question: Because of (T)Activator.CreateInstance( typeof(T) , args ) is NOT an option when you need a really strict compilation check. It is obvious that Activator not accomplish the basic principle (Derived classes and inherited behaviors must be used as to be possible instead of theirs final implementations - Liskov) that warranty Child Type have the behavior of the Parent Type even at compilation level.
The very-well known constraint in generic types is new(), it is possible to add parameters like (args,args,...) to force the compiler to check that the class contains a particular constructor?
While it feels like this should be available, it isn't. You can only add a constraint for a parameterless constructor.
As an alternative, consider passing a factory function. Here, you can specify the input arguments.
public class FooConstraint<T> where T : FooType
{
private readonly T _myObject;
public FooConstraint(Func<int, T> generator)
{
_myObject = generator(123);
}
}
Note: you could also store the Func
itself instead of immediately using it and discarding it. This is just an example.
Since the FooConstraint
class definition explicitly defines the Func<>
generic parameters, you can ensure that the consumer of FooConstraint
is aware exactly which constructor parameters your FooConstraint
will use to instantiate a T
instance.
var myConstraint = new FooConstraint<FooTypeChildA>(myInt => new FooTypeChildA(myInt));
Since you'll always just be calling a constructor and never doing anything fancy with the Func
, this feels like a bit of boilerplate, but given the absence of a true generic parametered constructor constraint, this is the closest alternative.