我正在编写一些代码,这些代码需要对从基类继承的每种类型做出不同的反应。 (注意:基类及其大部分子代不在我的控制范围内,所以我不能更改其中的一部分)
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(){ }
不起作用
答案 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);
}