I know, there are a few answers here on SO, which seem to solve my questions, like this and that threads. But in my specific case, there is some difference.
In front my question: Is this a possible/intelligent workaround to manage the new()
constraint in generics with parameters?
Assume the following base class:
abstract class BaseClass
{
internal BaseClass()
{
Console.WriteLine("{0}'s ctor (parameterless)", "BaseClass");
}
internal BaseClass(object parent)
{
Console.WriteLine("{0}'s ctor", "BaseClass");
Parent = parent;
}
public object Parent { get; private set; }
}
and interface:
interface IGenerate
{
IGenerate GenerateNew(int x, object parent);
}
The base class is only intended to store a parent object, the interface provides a method to return an object of the implementing class calling its constructor, like this:
class ClassX : BaseClass, IGenerate
{
public ClassX()
{
Console.WriteLine("{0}'s ctor (parameterless)", "ClassX");
}
public ClassX(int x, object parent)
: base(parent)
{
Console.WriteLine("{0}'s ctor", "ClassX");
X = x;
}
public IGenerate GenerateNew(int x, object parent)
{
Console.WriteLine("{0}.GenerateNew()", "ClassX");
return new ClassX(x, parent);
}
public int X { get; private set; }
}
My generic class is intended to generate and store an object of the provided class calling the interfaces method:
class MyGeneric<T> : BaseClass where T : IGenerate, new()
{
public MyGeneric(int x, object parent)
: base(parent)
{
Console.WriteLine("{0}'s ctor", "MyGeneric");
Instance = new T().GenerateNew(x, this);
}
public IGenerate Instance { get; private set; }
}
Another class inherits the generic:
class ClassXSpecifier : MyGeneric<ClassX>
{
public ClassXSpecifier(int x, object parent)
: base(x, parent)
{
Console.WriteLine("{0}'s ctor", "ClassXSpecifier");
}
}
The use of these constructs is something like that:
var classXspecifier = new ClassXSpecifier(5, null);
var classX = (ClassX)classXspecifier.Instance;
Console.WriteLine(classX.X);
Output:
BaseClass's ctor
MyGeneric's ctor
BaseClass's ctor (parameterless)
ClassX's ctor (parameterless)
ClassX.GenerateNew()
BaseClass's ctor
ClassX's ctor
ClassXSpecifier's ctor
5
Again my primary question: Is this a possible/intelligent workaround to manage the new()
constraint in generics with parameters?
A secondary question: Why do BaseClass
and ClassX
need to have a parameterless constructor while they won't be used in any case explicitly? If I remove them, I get the following error:
'ClassX' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'MyGeneric'
Thanks in advance, Christian =)
!!! SOLUTION !!!
The provided answer tempt me to do modifications, that the new()
constraint could be removed -> so the parameterless constructors could be removed, too.
I deleted the interface and added a static method into BaseClass
to generate new objects:
public static BaseClass GenerateNew(Type T, object[] args)
{
return (BaseClass)Activator.CreateInstance(T, args);
}
So the generic class could be reduced to
class MyGeneric<T> : BaseClass
{
public MyGeneric(int x, object parent)
: base(parent)
{
Console.WriteLine("{0}'s ctor", "MyGeneric");
Instance = GenerateNew(typeof(T), new[] { x, parent });
}
public BaseClass Instance { get; private set; }
}
That was it, thanks to all comments, too!