Игнорировать / перехватить "тип или пространство имен не найдено" - PullRequest
0 голосов
/ 25 августа 2018

Я делаю немного кода, который должен по-разному реагировать на каждый тип, унаследованный от базового класса. (примечание: базовый класс и большинство его детей вне моего контроля, поэтому я не могу поменять их части)

public void MethodName(BaseClass myObject)
{
   switch (myObject.GetType().ToString().Substring(myObject.GetType().ToString()
               .LastIndexOf(".") + 1))
   {
        case "ChildA":
            GUILayout.Label(((ChildA)myObject).sprite.texture);
            break;
        case "ChildB":
            GUILayout.Label(((ChildB)myObject).animated[0].texture);
        case "ChildC":
            GUILayout.Label(((ChildC)myObject).default.texture);
            break;
    }
}

У меня нет способа предсказать, какие классы будут иметь пользователи в своей сборке (например, A & B, нет, все три и т. Д.), Но если они пропустят какой-либо из них, это, очевидно, вернет ошибку, так как этот тип объекта не существует.

Поскольку каждый случай вызывается только в том случае, если класс этого случая существует, это никогда не будет проблемой. Я просто хочу, чтобы Visual Studio и компилятор замолчали около

Не удалось найти тип или имя пространства имен `ChildB '. Вам не хватает ссылки на сборку?

Кажется, что все подобные вопросы задают (и отвечают) о том, как это исправить, когда их класс не найден - но мне все равно, потому что я ЗНАЮ, что его не существует. Я не собираюсь импортировать класс или запускать эту строку кода, если класс не существует

try{ } catch(){ } не работает

Ответы [ 2 ]

0 голосов
/ 25 августа 2018

Вы получаете ошибку компилятора, а не ошибку времени выполнения.Поэтому try-catch не поможет.Проблема возникает из-за того, что класс ChildB находится в другом пространстве имен.Добавьте

using The.Other.Namespace;

… вверху вашего кода или, альтернативно, напишите

(The.Other.Namespace.ChildB)myObject

(Это полезно, если есть конфликт имен).

Примечание: ошибка компилятора возникает в результате статического анализа вашего кода.C # может обнаруживать синтаксические ошибки и очевидные логические ошибки, такие как использование несовместимых типов, использование неизвестных идентификаторов, неназначенных переменных и т. Д. В то время как во время выполнения вы можете получить исключения в зависимости от фактических значений, таких как: null-reference-exception, index-out-of-of-исключение границ, исключение деления на ноль и многое другое.


Имя класса можно получить с помощью myObject.GetType().Name.Кроме того, вместо использования "ChildA" было бы безопаснее написать nameof(ChildA), потому что тогда компилятор C # проверяет, чтобы имя было существующим именем, а переименовывающий рефакторинг будет учитывать это выражение.


Еще лучше: начиная с C # 7.0, вы можете использовать сопоставление с образцом в операторе switch:

switch (myObject)
{
    case ChildA childA:
        GUILayout.Label(childA.sprite.texture);
        break;
    case ChildB childB:
        GUILayout.Label(childB.animated[0].texture);
    case ChildC childC:
        GUILayout.Label(childC.default.texture);
        break;
}

Гораздо лучше: реализовать базовое свойство только для абстрактного метода получения LabelTexture и переопределить егов производных классах и пусть он возвращает соответствующую текстуру.Тогда вы можете просто получить текстуру с помощью myObject.LabelTexture (я не знаю, какой тип вы используете для texture, поэтому Image - это всего лишь предположение):

public abstract class BaseClass
{
    public abstract Image LabelTexture { get; }

    // ... other stuff
}

public class ClassA : BaseClass
{
    public override Image LabelTexture => sprite.texture;
}

public class ClassB : BaseClass
{
    public override Image LabelTexture => animated[0].texture;
}

public class ClassC : BaseClass
{
    public override Image LabelTexture => default.texture;
}

public override Image LabelTexture => sprite.texture; - этопросто более короткий синтаксис для public override Image LabelTexture { get { return sprite.texture; } }

Тогда получение правильной текстуры становится простым:

public void MethodName(BaseClass myObject)
{
    GUILayout.Label(myObject.LabelTexture);
}

Это называется Полиморфизм (Руководство по программированию в C #)

0 голосов
/ 25 августа 2018

Я думаю, что вы можете выразить это лучше, не используя Reflection.

Если вы используете C # 7, вы можете использовать сопоставление с шаблоном :

public void MethodName(BaseClass myObject)
{
    switch (myObject)
    {
        case ChildA a:
            GUILayout.Label(a.sprite.texture);
        case ChildB b:
            GUILayout.Label(b.animated[0].texture);
        case ChildC c:
            GUILayout.Label(c.default.texture);
    }
}

Если бы вы не могли сделать что-то вроде этого:

public void MethodName(BaseClass myObject)
{
    if (myObject is ChildA)
    {
        GUILayout.Label(((ChildA)myObject).sprite.texture);
    } else if (myObject is ChildB)
    {
        GUILayout.Label(((ChildB)myObject).animated[0].texture);
    } else if (myObject is ChildC)
    {
        GUILayout.Label(((ChildC)myObject).default.texture);
    } 
}

Но ваша главная проблема в том, что вам нужно добавить using, чтобы вы могли использовать ChildB.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...