【问题标题】:Set property of derived class on base class' instance在基类的实例上设置派生类的属性
【发布时间】:2018-09-19 06:55:26
【问题描述】:

我有一个这样的基类:

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

...和两个派生类:

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

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

在编译时,我知道我将处理Document 类型的对象。但是,只有在运行时我才知道它是 Bill 还是 Quote

我需要根据类型执行特定的操作,例如:

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

.. 但我不能这样编译,因为派生类的属性不能从基实例访问。

这样做的正确方法是什么? 这是fiddle to play around

【问题讨论】:

    标签: c#


    【解决方案1】:

    myDoc.advance 只能在编译器在编译时知道myDocBill 时才能编译。否则,myDoc 只是一个 Document 并且该类型没有 advance 成员。

    进行这样的类型检查不会修改myDoc 的静态类型。相反,您必须先将其类型转换为 Bill

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

    请注意,您应该使用is 运算符来验证myDoc 是否为Bill,而不是使用检查确切运行时类型的GetType()。您甚至可以使用 C# 中更新的模式匹配语法来使它更好:

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

    最后,请注意,通用约定是在 C# 中以 PascalCase 编写属性(即AdvanceNumberSumDiscount)。

    另请注意,默认情况下,类成员是私有的,因此您仍然无法访问这些属性。因此,您必须在属性定义前添加 public

    【讨论】:

    • 感谢您的解决方案以及在命名约定和访问器方面付出的额外努力!
    【解决方案2】:

    如果您使用 C# 7.0+,模式匹配是处理此问题的好方法

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

    【讨论】:

      【解决方案3】:

      你可以简单地投射它:

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

      【讨论】:

        猜你喜欢
        • 2018-03-21
        • 2014-06-27
        • 2021-10-08
        • 2020-03-28
        • 2015-08-26
        • 2011-11-04
        • 2013-02-12
        • 2023-03-19
        • 1970-01-01
        相关资源
        最近更新 更多