我试图在添加到列表时通过其构造函数创建一个T类型的新对象。

我得到一个编译错误:错误消息是:

'T':创建变量实例时不能提供参数

但是我的类确实有构造函数参数!我该怎么做呢?

public static string GetAllItems<T>(...) where T : new()
{
   ...
   List<T> tabListItems = new List<T>();
   foreach (ListItem listItem in listCollection) 
   {
       tabListItems.Add(new T(listItem)); // error here.
   } 
   ...
}

当前回答

使用c# 11中的静态抽象接口方法特性,可以使用工厂模式构建一个变通方案。例如:

public interface IFactory<TSelf> where TSelf : IFactory<TSelf> {
  static abstract TSelf New(int i, string s);
}

public struct Foo : IFactory<Foo> {

  public static Foo New(int i, string s) {
    return new Foo(i, s);
  }

  public readonly int I;
  public readonly string S;

  public Foo(int i, string s) {
    I = i;
    S = s;
  }
}

public static class Maker {
  public static T Make<T>(int i, string s) where T : IFactory<T> {
    return T.New(i, s);
  }
}

这种方法的一个限制是它只能用于您拥有的类,因为您需要在目标类上实现特定的工厂接口。

其他回答

在。net 3.5和之后,你可以使用activator类:

(T)Activator.CreateInstance(typeof(T), args)

因为没有人愿意发表“反思”的答案(我个人认为这是最好的答案),下面是:

public static string GetAllItems<T>(...) where T : new()
{
   ...
   List<T> tabListItems = new List<T>();
   foreach (ListItem listItem in listCollection) 
   {
       Type classType = typeof(T);
       ConstructorInfo classConstructor = classType.GetConstructor(new Type[] { listItem.GetType() });
       T classInstance = (T)classConstructor.Invoke(new object[] { listItem });

       tabListItems.Add(classInstance);
   } 
   ...
}

编辑:由于. net 3.5的Activator,这个答案已弃用。CreateInstance,但是它在旧的。net版本中仍然有用。

您需要在此处添加T: new(),以让编译器知道T保证提供默认构造函数。

public static string GetAllItems<T>(...) where T: new()

这在你的情况下行不通。你只能指定一个构造函数为空的约束:

public static string GetAllItems<T>(...) where T: new()

你可以通过定义这个接口来使用属性注入:

public interface ITakesAListItem
{
   ListItem Item { set; }
}

然后你可以改变你的方法如下:

public static string GetAllItems<T>(...) where T : ITakesAListItem, new()
{
   ...
   List<T> tabListItems = new List<T>();
   foreach (ListItem listItem in listCollection) 
   {
       tabListItems.Add(new T() { Item = listItem });
   } 
   ...
}

另一种替代方法是JaredPar描述的Func方法。

我认为必须用where语句约束T,以只允许具有新构造函数的对象。

现在它接受任何东西,包括没有它的对象。