在C#中是否有带参数约束的泛型构造函数?
在C#中,您可以对通用方法进行约束,如:在C#中是否有带参数约束的泛型构造函数?,c#,generics,parameters,constructor,generic-constraints,C#,Generics,Parameters,Constructor,Generic Constraints,在C#中,您可以对通用方法进行约束,如: public class A { public static void Method<T> (T a) where T : new() { //...do something... } } 解决方法也很有用?否。目前,您可以指定的唯一构造函数约束是无参数构造函数。没有此类构造函数。只能指定空构造函数约束 我用lambda方法解决了这个问题 public static void Method<T>
public class A {
public static void Method<T> (T a) where T : new() {
//...do something...
}
}
解决方法也很有用?否。目前,您可以指定的唯一构造函数约束是无参数构造函数。没有此类构造函数。只能指定空构造函数约束 我用lambda方法解决了这个问题
public static void Method<T>(Func<int,T> del) {
var t = del(42);
}
正如你所发现的,你不能这样做 作为一种解决方法,我通常提供一个可以创建
T
类型对象的委托:
public class A {
public static void Method<T> (T a, Func<float[,], T> creator) {
//...do something...
}
}
公共A类{
公共静态无效方法(TA,函数创建者){
//…做点什么。。。
}
}
我个人认为这是一个非常有效的解决方法。如果您想一想泛型参数化构造函数约束是什么,它实际上是具有特定签名的类型和构造函数之间的映射。您可以使用字典创建自己的映射。将它们放入静态“factory”类中,您可以创建各种类型的对象,而无需每次都构建构造函数lambda:
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) }
};
公共静态类BaseTypeFactory
{
私有委托BaseType BaseTypeConstructor(int-pParam1,int-pParam2);
专用静态只读字典
mTypeConstructors=新字典
{
{typeof(Object1),(pParam1,pParam2)=>newobject1(pParam1,pParam2)},
{typeof(Object2),(pParam1,pParam2)=>newobject2(pParam1,pParam2)},
{typeof(Object3),(pParam1,pParam2)=>newobject3(pParam1,pParam2)}
};
然后在通用方法中,例如:
public static T BuildBaseType<T>(...)
where T : BaseType
{
...
T myObject = (T)mTypeConstructors[typeof(T)](value1, value2);
...
return myObject;
}
publicstatict BuildBaseType(…)
其中T:BaseType
{
...
T myObject=(T)mtypeConstructor[typeof(T)](值1,值2);
...
返回myObject;
}
使用反射创建泛型对象时,类型仍然需要声明正确的构造函数,否则将引发异常。您可以传入任何参数,只要它们与其中一个构造函数匹配即可
使用这种方式,您不能在模板中的构造函数上设置约束。
如果缺少构造函数,则需要在运行时处理异常,而不是在编译时获得错误
// 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);
我认为这是对对象构造方式施加约束的最干净的解决方案。它不完全是编译时检查的。当您同意使类的实际构造函数具有与IConstructor接口相同的签名时,这有点像对构造函数施加约束de>Constructor方法在正常使用对象时是隐藏的,因为显式的接口实现
using System.Runtime.Serialization;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
var employeeWorker = new GenericWorker<Employee>();
employeeWorker.DoWork();
}
}
public class GenericWorker<T> where T:IConstructor
{
public void DoWork()
{
T employee = (T)FormatterServices.GetUninitializedObject(typeof(T));
employee.Constructor("John Doe", 105);
}
}
public interface IConstructor
{
void Constructor(string name, int age);
}
public class Employee : IConstructor
{
public string Name { get; private set; }
public int Age { get; private set; }
public Employee(string name, int age)
{
((IConstructor)this).Constructor(name, age);
}
void IConstructor.Constructor(string name, int age)
{
Name = name;
Age = age;
}
}
}
使用System.Runtime.Serialization;
名称空间控制台EAPP4
{
班级计划
{
静态void Main(字符串[]参数)
{
var employeeWorker=新的GenericWorker();
employeeWorker.DoWork();
}
}
公共类GenericWorker,其中T:IConstructor
{
公共工作
{
T employee=(T)FormatterServices.GetUninitializedObject(typeof(T));
建造商(“John Doe”,105);
}
}
公共接口IConstructor
{
void构造函数(字符串名,int-age);
}
公共类雇员:IConstructor
{
公共字符串名称{get;private set;}
公共整数{get;私有集;}
公共雇员(字符串名称,整数年龄)
{
((IConstructor)此)。构造函数(姓名、年龄);
}
void IConstructor.Constructor(字符串名称,整数年龄)
{
名称=名称;
年龄=年龄;
}
}
}
如何创建带有约束的泛型类,在这里我选择了struct和class来具有值和引用类型
这样,构造函数对值具有约束
class MyGenericClass其中T:struct其中X:class
{
私有T-genericMemberVariableT;
private X genericMemberVariableX;
公共MyGenericClass(T值T,X值X)
{
genericMemberVariableT=valueT;
genericMemberVariableX=valueX;
}
公共T genericMethod(T genericParameter)
{
WriteLine(“参数类型:{0},值:{1}”,typeof(T).ToString(),genericParameter);
WriteLine(“返回类型:{0},值:{1}”,typeof(T).ToString(),genericMemberVariableT);
WriteLine(“返回类型:{0},值:{1}”,typeof(X).ToString(),genericMemberVariableX);
返回genericMemberVariableT;
}
公共T genericProperty{get;set;}
}
实施:
MyGenericClass intGenericClass=新的MyGenericClass(10,“Hello world”);
int val=intGenericClass.genericMethod(200);
参数化构造函数约束是否出于逻辑原因而缺失,或者只是一些尚未添加到语言中的约束?同意……我们应该有
new(float,double)
,new(string)
,等等@Matthew不是每个类都有无参数构造函数,如果您用参数定义构造函数,而不重新定义默认构造函数,则没有默认构造函数。@Matthew这就是泛型类型约束的要点。您需要一个类,它派生自某个类,并包含一个带特定参数的构造函数s、 @bc3tech,从技术上讲,你的观点不是100%正确。如果一个基类没有默认构造函数,你必须提供一个调用其中一个基类构造函数的构造函数。你不必提供一个匹配的构造函数。这里有一个细微的区别……我现在使用这个,我认为这是一个很好的模式。效果非常好使用工厂模式。谢谢!这也可以扩展为基于其他数据创建类型。我在解析类似IFF的文件时经常使用这种类型的构造。我更喜欢在类型本身上定义静态构造函数,因此我的字典条目最终看起来像[“CELL”
// 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);
using System.Runtime.Serialization;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
var employeeWorker = new GenericWorker<Employee>();
employeeWorker.DoWork();
}
}
public class GenericWorker<T> where T:IConstructor
{
public void DoWork()
{
T employee = (T)FormatterServices.GetUninitializedObject(typeof(T));
employee.Constructor("John Doe", 105);
}
}
public interface IConstructor
{
void Constructor(string name, int age);
}
public class Employee : IConstructor
{
public string Name { get; private set; }
public int Age { get; private set; }
public Employee(string name, int age)
{
((IConstructor)this).Constructor(name, age);
}
void IConstructor.Constructor(string name, int age)
{
Name = name;
Age = age;
}
}
}
class MyGenericClass<T, X> where T :struct where X: class
{
private T genericMemberVariableT;
private X genericMemberVariableX;
public MyGenericClass(T valueT, X valueX)
{
genericMemberVariableT = valueT;
genericMemberVariableX = valueX;
}
public T genericMethod(T genericParameter)
{
Console.WriteLine("Parameter type: {0}, value: {1}", typeof(T).ToString(), genericParameter);
Console.WriteLine("Return type: {0}, value: {1}", typeof(T).ToString(), genericMemberVariableT);
Console.WriteLine("Return type: {0}, value: {1}", typeof(X).ToString(), genericMemberVariableX);
return genericMemberVariableT;
}
public T genericProperty { get; set; }
}
MyGenericClass<int, string> intGenericClass = new MyGenericClass<int, string>(10, "Hello world");
int val = intGenericClass.genericMethod(200);