C # цикл foreach вызывает CS 0246 Тип или пространство имен не может быть найден - PullRequest
1 голос
/ 20 августа 2009

У меня есть цикл foreach, который циклически перебирает список типов и создает экземпляр каждого из них. Однако при сборке выдает ошибку CS0246 («Не удалось найти тип или пространство имен ...»). Вот упрощенная версия кода:

internal static class TypeManager
{
    internal static void LoadTypes()
    {
        // Fill the list with types

        // Create instances of each type
        foreach (Type currType in Types)
        {
            Type aType = currType; // comiles fine
            Object newObj = (currType)Activator.CreateInstance<currType>; // CS 0246
        }
    }

    public static List<Type> Types;
}

Редактировать: следующий вопрос

Мой цикл foreach теперь выглядит следующим образом:

foreach (Type currType in Types)
{
    Types.Add((Type)Activator.CreateInstance(currType));
}

со списком типов теперь имеет тип Object

Это прекрасно компилируется, но когда я запускаю его, я получаю следующее:

Object reference not set to an instance of an object.

Если я разобью это на две строки, которые сначала создадут объект, затем добавят его в список, первая строка будет в порядке (объект успешно создан), но выдает мне то же сообщение об ошибке.

Редактировать: Обновить пример кода

internal static LoadPlugins()
{
    foreach (Type currType in pluginAssembly.GetTypes())
    {
        if (typeof(IPlugin).IsAssignableFrom(currType))
        {
            Assembly.LoadFrom(currFile.FullName);
            Object pluginInstance = Activator.CreateInstance(currType); // Compiles and runs fine
            Plugins.Add((IPlugin)pluginInstance); // NullReferenceException
            break;
        }
    }
}

public static List<IPlugin> Plugins;

Ответы [ 4 ]

4 голосов
/ 20 августа 2009

currType - это переменная, а не переменная типа, поэтому вы должны использовать неуниверсальную перегрузку:

Object newObj = Activator.CreateInstance(currType);
                                        ^        ^
4 голосов
/ 20 августа 2009

Обобщения должны быть известны во время компиляции. Вы не можете передать тип, определенный во время выполнения.

Так что вы можете сделать это:

(SomeType)Activator.CreateInstance<SomeType>;

но вы не можете сделать это:

(currType)Activator.CreateInstance<currType>;
1 голос
/ 20 августа 2009

Что касается продолжения: вам кажется, что вас смущает различие между понятиями «Обобщение» и «Отражение», возможно, вы захотите прочитать оба.

Что касается вашего дополнительного вопроса: вы приводите результат Activator.CreateInstance к System.Type, в то время как на самом деле вы должны приводить к фактическому типу. Если вы хотите привести обратно к фактическому типу, вам нужна дополнительная проверка во время выполнения.

Может быть, этот код поможет вам понять:

  var types = new List<Type>
    {
      typeof (string),
      typeof (DateTime)
    };

  foreach (Type t in types)
  {
    // creates an object of the type represented by t
    object instance = Activator.CreateInstance(t);

    // this would cause an InvalidCastException, since instance is not of type 
    // System.Type, but instead either of type System.String or System.DateTime
    // Type t2 = (Type) instance;

    // to cast back to the actual type, additional runtime checks are needed here:

    if (instance is System.String)
    {
      string s = (string) instance;
    }

    else if (instance is DateTime)
    {
      DateTime d = (DateTime) instance;
    }
  }
0 голосов
/ 26 июля 2011

Вы должны инициализировать свои переменные

public static List<IPlugin> Plugins=new List<IPlugin>();
...