代码之家  ›  专栏  ›  技术社区  ›  willeM_ Van Onsem

C中是否有带参数约束的泛型构造函数?

  •  139
  • willeM_ Van Onsem  · 技术社区  · 15 年前

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

    解决方法也很有用?

    6 回复  |  直到 7 年前
        1
  •  125
  •   user7116    12 年前

    正如你所发现的,你不能这样做。

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

    public class A {
    
        public static void Method<T> (T a, Func<float[,], T> creator) {
            //...do something...
        }
    
    }
    
        2
  •  40
  •   JaredPar    15 年前

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

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

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

    用例

    Method(x => new Foo(x));
    
        3
  •  38
  •   Sam Hanley    8 年前

    使用反射创建泛型对象时,类型仍然需要声明正确的构造函数,否则将引发异常。只要参数与其中一个构造函数匹配,就可以传入任何参数。

    通过这种方式,您不能在模板中对构造函数施加约束。 如果缺少构造函数,则需要在运行时处理异常,而不是在编译时获取错误。

    // 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);
    
        4
  •  16
  •   Dave Cousineau    13 年前

    这是一个我个人认为非常有效的解决方法。如果您考虑什么是通用的参数化构造函数约束,那么它实际上是具有特定签名的类型和构造函数之间的映射。您可以使用字典创建自己的此类映射。将它们放入静态的“工厂”类中,您可以创建不同类型的对象,而不必每次都担心构建构造函数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) }
       };
    

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

       public static T BuildBaseType<T>(...)
          where T : BaseType
       {
          ...
          T myObject = (T)mTypeConstructors[typeof(T)](value1, value2);
          ...
          return myObject;
       }
    
        5
  •  6
  •   Sean Reilly    15 年前

    不可以。目前唯一可以指定的构造函数约束是非参数构造函数。

        6
  •  3
  •   Mike de Klerk    7 年前

    我认为这是一个最干净的解决方案,它限制了对象的构造方式。它并不是完全经过编译时检查的。当您同意让类的实际构造函数具有与IConstructor接口相同的签名时,这有点像对构造函数有一个约束。这个 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;
            }
        }
    }
    
    推荐文章