在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>

在C#中,您可以对通用方法进行约束,如:

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