忽略/捕获“找不到类型或名称空间”

时间:2018-08-25 17:32:40

标签: c# unity3d

我正在编写一些代码,这些代码需要对从基类继承的每种类型做出不同的反应。 (注意:基类及其大部分子代不在我的控制范围内,所以我不能更改其中的一部分)

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 :(得分:0)

我认为您无需使用反射就能更好地表达这一点。

如果您使用的是C#7,则可以使用pattern matching

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。

答案 1 :(得分:0)

您得到的是编译器错误,而不是运行时错误。因此try-catch将无济于事。问题来自ChildB类在不同的命名空间中。添加

using The.Other.Namespace;

…在代码的顶部,或者编写

(The.Other.Namespace.ChildB)myObject

(如果发生名称冲突,这很有用。)

注意:静态分析代码会导致编译器错误。 C#可以检测语法错误和明显的逻辑错误,例如使用不兼容的类型,使用未知标识符,未分配的变量等。在运行时,您可以根据实际值获取异常,例如:null-reference-exception,index-out-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;
}

更好:在基类中实现仅抽象的getter属性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);
}

这称为Polymorphism (C# Programming Guide)