简体   繁体   English

在基类的实例上设置派生类的属性

[英]Set property of derived class on base class' instance

I have a base class like this: 我有一个这样的基类:

class Document {
    int number {get; set;}
    double sum {get; set;}
}

... and two derived classes: ...和两个派生类:

class Bill : Document {
    double advance {get; set;}
}

class Quote : Document {
    double discount {get; set;}
}

At compile time, I know that I'll be dealing with an object of type Document . 在编译时,我知道将要处理Document类型的对象。 However, it's only at runtime that I know whether it will be a Bill or a Quote . 但是,只有在运行时,我才能知道它是Bill还是Quote

I need to perform specific operations depending on the type, eg: 我需要根据类型执行特定的操作,例如:

if (myDoc.GetType() == typeof(Bill)) {
   myDoc.advance = 1000; //<-- can't find "advance"
}

.. but I can't compile like that as the properties of the derived class is not accessible from a base instance. ..但我不能那样编译,因为无法从基实例访问派生类的属性。

What is the proper way of doing that? 这样做的正确方法是什么? Here's a fiddle to play around . 这是一个玩弄小提琴

myDoc.advance can only compile if the compiler can tell at compile time that myDoc is a Bill . myDoc.advance只能编译如果编译器在编译时告诉myDocBill Otherwise, myDoc is just a Document and that type does not have an advance member. 否则, myDoc只是一个Document并且该类型没有advance成员。

Doing a type check like that will not modify the static type of myDoc . 进行类似的类型检查不会修改myDoc的静态类型。 Instead, you would have to type cast it into a Bill first: 相反,您必须先将其类型转换为Bill

Bill myBill = (Bill)myDoc;
myBill.advance = 1000;

Note that instead of using GetType() which checks the exact runtime type, you should be using the is operator to verify that myDoc is a Bill . 请注意,您应该使用is运算符来验证myDocBill ,而不是使用检查确切的运行时类型的GetType() You can even use the newer pattern matching syntax from C# to make this nicer: 您甚至可以使用C#中较新的模式匹配语法来使此更好:

if (myDoc is Bill myBill) {
    myBill.advance = 1000;
}

Finally, please note that the common convention is to write properties in C# in PascalCase (ie Advance , Number , Sum and Discount ). 最后,请注意,通用约定是在PascalCase中用C#编写属性(即AdvanceNumberSumDiscount )。

Also note that class members are private by default, so you still wouldn't be able to access those properties. 另请注意,默认情况下,类成员是私有的,因此您仍然无法访问这些属性。 So you would have to add a public in front of the property definitions. 因此,您必须在属性定义前面添加一个public

Pattern matching is a good way to handle this if you are using C# 7.0+ 如果您使用的是C#7.0+,则模式匹配是解决此问题的好方法

if(myDoc is Bill bill)
{
    bill.Advance = 1000;
}
else if(myDoc is Quote quote)
{
    quote.Discount = 1000;
}

You can simply cast it: 您可以简单地将其转换为:

if (myDoc.GetType() == typeof(Bill))
{
    ((Bill)myDoc).advance = 1000;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM