我有一个专门的泛型集合类,它将用于保存许多不同类型的对象的集合。创建集合后,我需要实例化集合的项目。我有最艰难的时间让这个工作。必须有一个我想念的简单解决方案。
这是一个示例类,它说明了我要做的事情以及我遇到的警告/错误。
// Note: T may either a string or other reference type that supports IEnumerable.
public class Foo<T>
{
private List<T> fooBarList = new List<T>();
public Foo()
{
Bar1<T>();
Bar2<T>();
Bar3<T>();
}
public void Bar1<T>()
{
// Error Message: Argument 1 cannot convert from 'T...' to 'T...'
T t = default;
fooBarList.Add(t);
}
public void Bar2<T>() where T : IEnumerable, new()
{
// Error Message: T must be a non-abstract type with public
// parameterless constructor in order to use it as a parameter 'T'
// in the generic type or method 'Foo<T>.Bar2<T>()
fooBarList.Add(new T());
}
public void Bar3<T>() where T : IEnumerable, new()
{
// Error Message: Argument 1 cannot convert from 'T...' to 'T...'
T t = Activator.CreateInstance<T>();
fooBarList.Add(t);
}
}
旁注:这个特殊的代码在我的应用程序中是一个特别重要的性能部分 - 你知道,3%的Donald Knuth谈到需要实际优化。这确实需要很快,因为每次应用程序执行会被调用数百万次。如果有任何其他选择,我不会热衷于使用反射(例如Activator.CreateInstance())。 (就目前而言,即使这对我来说似乎也不起作用。)我宁愿让编译器在编译时解析数据类型。
这个问题已在下面的链接中得到解答,但这些方法似乎都不适合我。我错过了什么?
In C#, how to instantiate a passed generic type inside a method?
仅供参考,我在运行Visual Studio 2019企业预览版的Windows 10计算机上使用.NET Core 2.2 Beta和.NET Standard 2.0。
似乎List<T>
已经拥有了你需要的所有东西,除了一个创建新实例并添加它的方法,它可以作为扩展方法添加:
public static ICollectionExtensions
{
public static AddNew<T>(this ICollection<T> collection)
where T : new()
{
var newItem = new T();
collection.Add(newItem);
}
...
}
可以像这样使用:
var list = new List<int>();
list.AddNew();
这编译:
public class Foo<T> where T : IEnumerable, new()
{
private List<T> fooBarList = new List<T>();
public Foo()
{
Bar1();
Bar2();
Bar3();
}
public void Bar1()
{
T t = default(T);
fooBarList.Add(t);
}
public void Bar2()
{
fooBarList.Add(new T());
}
public void Bar3()
{
T t = Activator.CreateInstance<T>();
fooBarList.Add(t);
}
}
请注意,T
的唯一声明在类级别上升,包括<T>
部分和where
部分。