我试图在添加到列表时通过其构造函数创建一个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# >= 3中你可以很容易地做到:

public static string GetAllItems<T>(...) where T : InterfaceOrBaseClass, new() 
{ 
   ... 
   List<T> tabListItems = new List<T>(); 
   foreach (ListItem listItem in listCollection)  
   { 
       tabListItems.Add(new T{ BaseMemberItem = listItem }); // No error, BaseMemberItem owns to InterfaceOrBaseClass. 
   }  
   ... 
} 

这和Garry Shutler说的一样,但我想补充一点。

当然,您可以使用属性技巧来做更多的事情,而不仅仅是设置字段值。 属性“set()”可以触发设置其相关字段所需的任何处理,以及对对象本身的任何其他需求,包括在使用对象之前检查是否要进行完整的初始化,模拟完整的构造(是的,这是一个丑陋的解决方法,但它克服了M$ new()的限制)。

我不能确定这是一个计划好的漏洞还是一个意外的副作用,但它确实有效。

有趣的是,微软的人给语言添加了新功能,却似乎没有做一个完整的副作用分析。 整个通用的东西就是一个很好的证据…

其他回答

如果你只是想用构造函数参数初始化一个成员字段或属性,在c# >= 3中你可以很容易地做到:

public static string GetAllItems<T>(...) where T : InterfaceOrBaseClass, new() 
{ 
   ... 
   List<T> tabListItems = new List<T>(); 
   foreach (ListItem listItem in listCollection)  
   { 
       tabListItems.Add(new T{ BaseMemberItem = listItem }); // No error, BaseMemberItem owns to InterfaceOrBaseClass. 
   }  
   ... 
} 

这和Garry Shutler说的一样,但我想补充一点。

当然,您可以使用属性技巧来做更多的事情,而不仅仅是设置字段值。 属性“set()”可以触发设置其相关字段所需的任何处理,以及对对象本身的任何其他需求,包括在使用对象之前检查是否要进行完整的初始化,模拟完整的构造(是的,这是一个丑陋的解决方法,但它克服了M$ new()的限制)。

我不能确定这是一个计划好的漏洞还是一个意外的副作用,但它确实有效。

有趣的是,微软的人给语言添加了新功能,却似乎没有做一个完整的副作用分析。 整个通用的东西就是一个很好的证据…

您需要在此处添加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方法。

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

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

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

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