Подтвердить что ты не робот

Динамически объявлять экземпляр типового типа

Можно ли объявить экземпляр родового без знания типа во время разработки?

Пример:

Int i = 1;
List<typeof(i)> list = new List<typeof(i)>();

где тип я может быть чем угодно, вместо того, чтобы делать:

List<int> list = new List<int();
4b9b3361

Ответ 1

Если вы не знаете тип во время компиляции, но хотите фактический тип (т.е. не List<object>), и вы не используете общий метод/тип с соответствующим параметром типа, тогда вам нужно использование отражение.

Чтобы сделать отражение проще, я иногда вводил новый родовой тип или метод в свой собственный код, поэтому я могу назвать это отражением, а затем просто использовать обычные дженерики после этого. Например:

object x = GetObjectFromSomewhere();
// I want to create a List<?> containing the existing
// object, but strongly typed to the "right" type depending
// on the type of the value of x
MethodInfo method = GetType().GetMethod("BuildListHelper");
method = method.MakeGenericMethod(new Type[] { x.GetType() });
object list = method.Invoke(this, new object[] { x });

// Later

public IList<T> BuildListHelper<T>(T item)
{
    List<T> list = new List<T>();
    list.Add(item);
    return list;
}

Конечно, после того, как вы не знаете тип, вы не сможете сделать много со списком, потому что это часто падает. Не всегда, хотя я несколько раз использовал что-то подобное выше, где система типов просто не позволяет мне выразить все, что мне нужно, статически.

EDIT: Обратите внимание, что хотя я вызываю Type.GetMethod в приведенном выше коде, если вы собираетесь его выполнить, вы, вероятно, захотите просто называть его один раз - в конце концов, метод не собирается изменение. Вы можете сделать его статическим (вы могли бы в случае выше), и вы, вероятно, захотите сделать его приватным. Я оставил его как метод публичного экземпляра для простоты вызова GetMethod в примере кода - вам нужно указать соответствующие флаги привязки в противном случае.

Ответ 2

Я думаю, что лучшее, что вы собираетесь сделать, это что-то вроде этого:

static void Main(string[] args)
{
    int i = 1;
    var thelist = CreateList(i);
}

public static List<T> CreateList<T>(T t)
{
    return new List<T>();
}

Ответ 3

Если вы не знаете тип во время разработки, я бы сказал, что у вас есть список OBJECTS (базовый класс для всех других типов).

List<object> list = new List<object>();

Ответ 4

Вы также можете использовать Activator.CreateInstance. Пример фрагмента кода:

public class BaseRepository<T> where T : DataContext
{
   protected T _dc;

   public BaseRepository(string connectionString)
   {
      _dc = (T) Activator.CreateInstance(typeof(T), connectionString);
   }

   public void SubmitChanges()
   {
      _dc.SubmitChanges();
   }
}

Ответ 6

См. ответ по аналогичному вопросу "Динамическое создание типового типа для шаблона" . Единственное различие заключается в том, что они генерируют тип из командной строки, а остальные вы должны быть способны адаптироваться к вашим потребностям.

В стороне вы не можете вызвать typeof для экземпляра - чтобы получить тип экземпляра (например, "i" вызвать GetType():

Type intType = i.GetType();

Ответ 7

Если вы все еще хотите ввести .Add(),.Remove(), сделать foreach и т.д., вы можете рассматривать List как обычный "старый" System.Collections.IList, поскольку этот интерфейс, к счастью, реализован List <T> .

И поскольку все остальные опубликованные ответы на этот вопрос показывают практически все возможные способы создания экземпляра List <T> динамически, я покажу последний способ сделать это. Я лично использую этот метод при создании общих экземпляров, когда я вообще ничего не знаю о типе во время компиляции, и тип должен быть передан как строка, возможно, из файла конфигурации приложения. В этом примере T является System.String для простоты, но это может быть что угодно:

Type T = typeof ( string ); // replace with actual T
string typeName = string.Format (
  "System.Collections.Generic.List`1[[{0}]], mscorlib", T.AssemblyQualifiedName );

IList list = Activator.CreateInstance ( Type.GetType ( typeName ) )
  as IList;

System.Diagnostics.Debug.Assert ( list != null ); //

list.Add ( "string 1" ); // new T
list.Add ( "string 2" ); // new T
foreach ( object item in list )
{
  Console.WriteLine ( "item: {0}", item );
}