代码之家  ›  专栏  ›  技术社区  ›  Edward Tanguay

使用C泛型作为构造函数名的语法是什么?

  •  0
  • Edward Tanguay  · 技术社区  · 16 年前

    我有许多类继承自 Item<T> .

    每个类都有一个create()方法,我希望将其移到 项目& T; .

    但是下面的代码得到了错误“ 无法创建变量类型“t”的实例,因为它没有new()约束 “:

    T item = new T(loadCode);
    

    什么是 更正语法 这样做?

    public abstract class Item<T> : ItemBase
    {
    
        public static T Create(string loadCode)
        {
            T item = new T(loadCode);
    
            if (!item.IsEmpty())
            {
                return item;
            }
            else
            {
                throw new CannotInstantiateException();
            }
        }
    
    4 回复  |  直到 16 年前
        1
  •  9
  •   Mehrdad Afshari    16 年前

    这是不可能的。你只能用 new() 强制存在构造函数的约束。

    解决方法是 Func<InputType, T> ( Func<string,T> 在您的示例中)委托作为将为我们创建对象的输入参数。

    public static T Create(string loadCode, Func<string,T> construct)
    {
        T item = construct(loadCode);
    
        if (!item.IsEmpty())
        {
            return item;
        }
        else
        {
            throw new CannotInstantiateException();
        }
    }
    

    并用以下方式称呼它: Item<T>.Create("test", s => new T(s));

        2
  •  3
  •   jerryjvl    16 年前

    修正 :我犯了一个小错误,对于这个解决方案,您需要另一个对t的约束,请参见下面的代码。

    您只能为无参数构造函数设置一个约束,但这样的方法可能会奏效:

    public interface ILoadable
    {
        void Load(string loadCode);
    }
    
    public abstract class Item<T> : ItemBase
        where T : ILoadable, new()
    {
        public static T Create(string loadCode)
        {
            T item = new T();
            item.Load(loadCode);
    
            if (!item.IsEmpty())
            {
                return item;
            }
            else
            {
                throw new CannotInstantiateException();
            }
        }
    }
    

    然后实现依赖于 loadCode 在覆盖到 Load(...) 在后代阶级。

        3
  •  1
  •   vgru    16 年前

    你可以使用 Activator.CreateInstance 创建实例,尽管它不执行任何编译时检查。

        4
  •  1
  •   samjudson    16 年前

    错误是因为编译器不能依赖于这样一个事实:泛型类T除了默认的构造函数之外还有其他任何东西。

    您可以使用反射来克服这一点,如下所示:

    ConstructorInfo c = typeof(T).GetConstructor(new Type[] { typeof(string) });
    T t = (T)c.Invoke(new object[] { loadCode });
    

    因此,由于T类型必须有一个采用字符串的构造函数,因此我还将限制您的类,以便它必须从具有构造函数的类继承:

    class Item<T> : ItemBase where T : BaseClassWithConstructor