2009-12-05 104 views
123

在C#中,你可以把一个约束在一个通用的方法,如:在C#中有参数约束的泛型构造函数吗?

public class A { 

    public static void Method<T> (T a) where T : new() { 
     //...do something... 
    } 

} 

如果您指定T应该有一个不需要参数的构造函数。我不知道是否有添加约束类似的方式

下面的代码无法编译“存在有float[,]参数的构造函数?”:

public class A { 

    public static void Method<T> (T a) where T : new(float[,] u) { 
     //...do something... 
    } 

} 

一种解决方法是也有用?

+0

的可能重复[如何约束通用类型必须有一个construtor这需要一定的参数?](http://stackoverflow.com/questions/853703/how-to-constrain-generic-type-to -must-have-a-construtor-that-c​​ertain-certain-param) – nawfal 2014-07-16 14:52:10

回答

115

正如您看到的,你不能做到这一点。

作为一种变通方法,我通常提供一个委托,它可以创建T类型的对象:

public class A { 

    public static void Method<T> (T a, Func<float[,], T> creator) { 
     //...do something... 
    } 

} 
+37

是参数化的构造函数约束由于逻辑原因而缺失,还是仅仅是尚未被添加到语言中的东西? – 2011-08-23 03:34:12

+18

同意......我们应该有'new(float,double)','new(string)'等等 – SliverNinja 2012-02-01 17:47:15

+8

@Sahuagin我认为这是不可能的,因为当你从一个类继承时,不能保证子类具有构造函数被定义,因为构造函数没有被继承。然而,每个类都有一个空的参数构造函数。 – Matthew 2012-03-03 00:21:20

5

否。目前唯一可以指定的构造函数约束是针对无参数构造函数的。

39

没有这样的结构。您只能指定一个空的构造函数约束。

我用lambda方法解决了这个问题。

public static void Method<T>(Func<int,T> del) { 
    var t = del(42); 
} 

使用案例

Method(x => new Foo(x)); 
+0

没有办法在'Method'内抽象创建'Foo'? – 2015-11-13 15:52:24

+0

如果Method的用户使用Method(x => new Foo());'?无论如何确保lambda应该是这样吗? – 2015-11-13 15:53:31

15

这是解决类似的问题,我个人觉得相当有效。如果你想到通用的参数化构造函数约束是什么,它实际上是具有特定签名的类型和构造函数之间的映射。您可以使用字典创建自己的这种映射。在一个静态的“工厂”类把这些和你可以不必担心每次建立一个构造函数拉姆达创建不同类型的对象:

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

然后在通用的方法,例如:

public static T BuildBaseType<T>(...) 
     where T : BaseType 
    { 
     ... 
     T myObject = (T)mTypeConstructors[typeof(T)](value1, value2); 
     ... 
     return myObject; 
    } 
+1

为什么这配得上拇指?根据我的经验,它工作得很好。 – 2012-02-09 02:35:31

+1

我现在使用这个,我认为这是一个很好的模式。工厂模式非常好。谢谢! – Matthew 2012-03-02 20:46:14

32

使用反射来创建通用对象,该类型仍需要声明正确的构造函数或引发异常。只要符合其中一个构造函数,就可以传入任何参数。

使用这种方式,您不能在模板中的构造函数上施加约束。 如果缺少构造函数,则需要在运行时处理异常,而不是在编译时收到错误。

// 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); 
相关问题