У меня есть специализированный универсальный класс коллекций, который будет использоваться для хранения коллекций различных типов объектов. Как только коллекция создана, мне нужно создать ее элементы. У меня самое страшное время заставить это работать. Там должно быть простое решение, которое я пропускаю.
Вот пример класса, который как бы иллюстрирует то, что я пытаюсь сделать, и предупреждения/ошибки, с которыми я сталкиваюсь.
// 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% Дональд Кнут говорит о необходимости оптимизации. Это действительно должно быть быстрым, потому что оно будет вызываться миллионы раз за выполнение приложения. Я не был бы в восторге от использования отражения (например, Activator.CreateInstance() здесь), если есть какая-либо другая альтернатива. (На данный момент даже это, похоже, не работает для меня.) Я бы предпочел, чтобы компилятор разрешил тип данных во время компиляции.
На этот вопрос уже ответили по ссылке ниже, но ни один из подходов, похоже, не работает для меня. Что мне не хватает?
В С# как создать экземпляр переданного универсального типа внутри метода?
К вашему сведению, я использую .NET Core 2.2 Beta и .NET Standard 2.0 на компьютере с Windows 10 под управлением Visual Studio 2019 Enterprise Preview.
Кажется, что 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
.
new()
...
public void Bar1<T>()
... должен бытьpublic void Bar1()
, эти методы не должны быть универсальными, а скорее использовать универсальный тип класса<T>
на уровне функции.