简体   繁体   English

在C#中实例化泛型类型的实例

[英]Instantiate an instance of a generic type in C#

I have a specialized generic collection class which will be used to hold collections of many different types of objects. 我有一个专门的通用集合类,它将用于保存许多不同类型的对象的集合。 Once the collection is created, I need to instantiate the collection's items. 创建集合后,我需要实例化集合的项目。 I am having the darnedest time getting this to work. 我有最迫切的时间让它工作。 There must be a simple solution I am missing. 我必须缺少一个简单的解决方案。

Here is a sample class which kind of illustrates what I am trying to do and the warnings/errors I am bumping up against. 这是一个示例类,用于说明我正在尝试执行的操作以及遇到的警告/错误。

// 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);
    }
}

Side note: This particular code is in a particularly performance-critical part of my application--you know, the 3% Donald Knuth talks about needing to actually be optimized. 旁注:此特定代码在我的应用程序中对性能至关重要的部分中-您知道,3%的Donald Knuth谈到需要进行实际优化。 This really does need to be fast because it will get called millions of times per application execution. 这确实需要快速,因为每个应用程序执行将被调用数百万次。 I would not be at all enthusiastic about using reflection (eg Activator.CreateInstance() here) if there is any other alternative. 如果有其他选择,我对使用反射(例如此处的Activator.CreateInstance())一点也不热心。 (For now, even that does not seem to be working for me.) I would much rather have the compiler resolve the data type at compile time. (就目前而言,即使对于我来说似乎也不起作用。)我宁愿让编译器在编译时解析数据类型。

This question was already answered in the link below, but none of the approaches seem to be working for me. 下面的链接中已经回答了这个问题,但是似乎没有一种方法对我有用。 What am I missing? 我想念什么?

In C#, how to instantiate a passed generic type inside a method? 在C#中,如何实例化方法内部传递的泛型类型?

FYI, I am using .NET Core 2.2 Beta and .NET Standard 2.0 on a Windows 10 machine running Visual Studio 2019 Enterprise Preview. 仅供参考,我正在运行Visual Studio 2019企业预览版的Windows 10计算机上使用.NET Core 2.2 Beta和.NET Standard 2.0。

It seems like List<T> already has all you need except a method to create a new instance and add it, which could be added as extension methods: 似乎List<T>已经拥有您所需的全部内容,只是创建新实例并添加它的方法,可以将其添加为扩展方法:

public static ICollectionExtensions
{
    public static AddNew<T>(this ICollection<T> collection)
        where T : new()
    {
        var newItem = new T();
        collection.Add(newItem);
    }

    ...
} 

which can be used like this: 可以这样使用:

var list = new List<int>();
list.AddNew();

This compiles: 这样编译:

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);
    }
}

Note that the only declaration of T is up at the class level, both the <T> part and the where part. 请注意, T的唯一声明是在类级别上的,包括<T>部分和where部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM