我是编程和C#的新手,我只是想知道如果我的引用变量是超类类型,是否可以通过属性初始化子类字段。
示例
Character test = new Archer();
test.Damage = 5; // Damage is from the Fighter Class
SuperClass 字符
abstract class Character
{
//Superclass common
}
字符
的战斗机子类abstract class Fighter : Character
{
private int damage
public int Damage {
get
{
return damage;
}
set
{
damage = value;
}
}
}
战斗机
的 Archer 子类class Archer : Fighter
{
//stuffs that only archers can do
}
答案 0 :(得分:9)
我是编程和c#的新手
欢迎您的光临。首先,我要鼓励您获得一本好书,上一门课程,找一位导师,或者您为学习一门学科所做的一切。 StackOverflow显然不是教程站点。
如果我的引用变量是超类类型,是否可以通过属性初始化子类字段?
初学者程序员的答案是:不。
如果要访问派生类型更多的属性,则必须知道该引用属于该派生类型。
C#是我们所谓的“静态类型”语言,这意味着必须有“静态”(即编译器已知)类型信息,以证明每个表达式都是有效的。
高级程序员的答案是:是的,但是不要这样做。
C#具有“动态”模式;如果你说
dynamic test = new Archer();
test.Damage = 123;
那行得通。 不这样做。有两个原因。首先,如果您关闭静态类型检查,则会关闭静态类型检查。你可以写
dynamic test = new Archer();
test.Damaeg = 123;
,编译器将允许它,并且您的程序将在运行时崩溃。 静态类型检查可为您提供帮助。使用它。
第二,我们添加了dynamic
,以便人们可以编写与动态语言(例如Python和JavaScript)交互的C#程序。为此,请在需要时使用它,而不是最终绕过静态类型检查。
我应该使用最具体的课程吗?
您应该使用一个足够具体的类。在这种情况下,可以使用Fighter
或Archer
。
我们正在查看您的代码时,还有其他一些评论:
private int damage
public int Damage {
get
{
return damage;
}
set
{
damage = value;
}
那是正确的,但是这就是您在C#1.0中编写它的方式。从3.0以后的任何版本的C#中,您通常都会编写简短得多的形式:
public int Damage { get; set; }
,让编译器为您管理后备字段。
还请考虑:*您是否想在类层次结构之外设置Damage
属性?如果答案为“否”,则将其设置为protected set;
属性。您是否希望在Fighter
类之外设置它?如果不是,请将其设置为private set;
,是否希望它在初始设置后就可以全部设置为 ?如果否,则(在C#7中)完全省略set
,它将只能在构造函数中设置。
此外,这可能对您现在来说太高级了,但它也可能使您走上一条艰难的道路。我写了一系列文章,专门讨论您正在探索的问题空间,以及即使是高级程序员也可能遇到的常见陷阱。它从这里开始:https://ericlippert.com/2015/04/27/wizards-and-warriors-part-one/-在该系列中,我还将详细讨论滥用dynamic
。
答案 1 :(得分:0)
回答问题,您可以设置值,您只需要在以下位置进行强制转换即可:
(test as Archer).Damage = 5;
//Or
//(test as Fighter).Damage = 5;
现在,如果您应该这样做,请查看Eric的答案和他的博客。