基本上有2个班级。
class Motor {
int a;
int b;
int c;
}
class Title : Motor {
int d;
int e;
}
Run Code Online (Sandbox Code Playgroud)
现在,函数将与Motor类的实例一起传递。
bool AssignNums(Motor m)
{
Title t = (Title)m; //throws exception
//Do other things with "t"
}
Run Code Online (Sandbox Code Playgroud)
叫做,
void AddNums()
{
Motor m = new Motor();
m.a = 23;
m.b = 78;
m.c = 109;
AssignNums(m);
}
Run Code Online (Sandbox Code Playgroud)
上面的强制转换行无效。它抛出一个空指针异常。
我试过了:
bool AssignNums(Motor m)
{
Title t = new Title();
t = (Title)m; // Doesn't work.
//Do other things with "t"
}
Run Code Online (Sandbox Code Playgroud)
上面的方法也不起作用。
来自C ++背景,很难理解C#在C#中是如何工作的。
在C ++中,以下代码将起作用。
bool AssignNums(Motor* m)
{
Title* t = (Title*)m; //Will work
//Do other things with "t"
}
Run Code Online (Sandbox Code Playgroud)
如何在C#中完成?无需大量代码即可实现“反射”或类似功能……
在C#中,您不能将对象转换为更特定的子类。想象一下如果可能的话会发生什么:
class Foo : Motor
{
int z;
}
Foo m = new Foo();
bool AssignNums(Motor m)
{
Title t = (Title)m; // Pretend it doens't throw an exception
//Do other things with "t"
t.d = 42; // Oopps! The actual object is Foo, not Title, so there is no field called d
// InvalidCastException is thrown at the line that attempts the cast
}
Run Code Online (Sandbox Code Playgroud)
如果实际类型与所需类型兼容,则可以在运行时对其进行转换:
bool AssignNums(Motor m)
{
Title t = m as Title;
if (t != null)
{
// Do stuff with t
}
}
Run Code Online (Sandbox Code Playgroud)
从C#7开始,您可以使用较短的形式
bool AssignNums(Motor m)
{
if (m is Title t)
{
// Do stuf with t
}
}
Run Code Online (Sandbox Code Playgroud)
如果处理多个子类,则还可以使用switch..when
switch (m)
{
case Title t when m is Title:
// Do something with t
break;
case Foo f when m is Foo:
// Do something with f
break;
}
Run Code Online (Sandbox Code Playgroud)
但是请注意,如果您基于运行时存在的子类进行分支,则表明您可能存在设计问题。