Problem
In C#, you can limit a generic method by using the following syntax:
public class A {
public static void Method<T> (T a) where T : new() {
//...do something...
}
}
Where you say that T should have a constructor that doesn’t take any arguments. I’m wondering if it’s possible to add a constraint like “a constructor with a float[,] parameter exists?”
The code below fails to compile:
public class A {
public static void Method<T> (T a) where T : new(float[,] u) {
//...do something...
}
}
Isn’t it also possible to find a workaround?
Asked by Willem Van Onsem
Solution #1
You can’t do it, as you’ve discovered out.
As a workaround, I usually provide a delegate that can construct T-type objects:
public class A {
public static void Method<T> (T a, Func<float[,], T> creator) {
//...do something...
}
}
Answered by Tim Robinson
Solution #2
When creating a generic object with reflection, the type must still have the correct constructor defined or an exception will be issued. Any argument can be passed in as long as it matches one of the constructors.
You can’t put a constraint on the constructor in the template this way. Instead of obtaining an error at build time, if the constructor is missing, an exception must be handled at run-time.
// public static object CreateInstance(Type type, params object[] args);
// Example 1
T t = (T)Activator.CreateInstance(typeof(T));
// Example 2
T t = (T)Activator.CreateInstance(typeof(T), arg0, arg1, arg2, ...);
// Example 3
T t = (T)Activator.CreateInstance(typeof(T), (string)arg0, (int)arg1, (bool)arg2);
Answered by xpress
Solution #3
Such a thing does not exist. An empty constructor constraint is the only one you can use.
I use lambda methods to get around this issue.
public static void Method<T>(Func<int,T> del) {
var t = del(42);
}
Use Case
Method(x => new Foo(x));
Answered by JaredPar
Solution #4
This is a solution that I have found to be fairly effective. A generic parameterized constructor constraint is basically a mapping between types and constructors with a specific signature, if you think about it. Using a dictionary, you can design your own mapping. Put these in a static “factory” class, and you’ll be able to generate objects of various types without having to worry about writing a constructor lambda every time:
public static class BaseTypeFactory
{
private delegate BaseType BaseTypeConstructor(int pParam1, int pParam2);
private static readonly Dictionary<Type, BaseTypeConstructor>
mTypeConstructors = new Dictionary<Type, BaseTypeConstructor>
{
{ typeof(Object1), (pParam1, pParam2) => new Object1(pParam1, pParam2) },
{ typeof(Object2), (pParam1, pParam2) => new Object2(pParam1, pParam2) },
{ typeof(Object3), (pParam1, pParam2) => new Object3(pParam1, pParam2) }
};
then, for example, in your generic method:
public static T BuildBaseType<T>(...)
where T : BaseType
{
...
T myObject = (T)mTypeConstructors[typeof(T)](value1, value2);
...
return myObject;
}
Answered by Dave Cousineau
Solution #5
No. The only constructor constraint you can express at the moment is for a no-arg constructor.
Answered by Sean Reilly
Post is based on https://stackoverflow.com/questions/1852837/is-there-a-generic-constructor-with-parameter-constraint-in-c