【问题标题】:C# Inheritance - Differentiating Derived-Object From Base-ObjectC# 继承 - 区分派生对象和基对象
【发布时间】:2013-06-27 20:12:55
【问题描述】:

在库存程序中,我创建了类Item 和ItemCollection,以及派生类Computer : Item。

在一个表单中,我创建了一个名为TheseItems(包括一些计算机)的ItemCollection(Items 的通用列表),我想显示每个项目ThisItem 的属性(如位置、数量等)。

在执行此操作时,我还想显示计算机的不同属性(例如 CPU、HDD 和 RAM)。到目前为止我有这个:

foreach (Item ThisItem in TheseItems)
{
    //Display properties of Item instance “ThisItem” (Excluded for ease of reading)

    if (ThisItem is Computer)
    {
        //Display distinct properties of Computer instance “ThisItem”
    }
}

到目前为止,没有错误,但我不确定如何继续。有没有可能做我想做的事?

编辑:谢谢,牛排!我担心强制转换不允许我访问预先分配的属性(并且只允许分配新的属性),但幸运的是我错了!我现在有:

Computer ThisComputer = ThisItem as Computer;
if (Computer != null)
{
     //Display distinct properties of Computer instance “ThisComputer”
}

我收到的快速帮助给我留下了深刻的印象。谢谢!

【问题讨论】:

  • 你所拥有的将起作用。

标签: c# inheritance derived-class base-class ienumerator


【解决方案1】:

你所拥有的将起作用。

foreach (Item ThisItem in TheseItems)
{
    //Display properties of Item instance “ThisItem” (Excluded for ease of reading)

    if (ThisItem is Computer)
    {
        Computer computerItem = (Computer)ThisItem;
        //Display distinct properties of Computer instance “ThisItem”
    }
}

或使用as 关键字进行轻微优化:

foreach (Item ThisItem in TheseItems)
{
    //Display properties of Item instance “ThisItem” (Excluded for ease of reading)
    var computerItem = ThisItem as Computer;
    if (computerItem != null)
    {
        //Display distinct properties of Computer instance “ThisItem”
    }
}

另外,我的一个朋友写了一个很好的实用程序类来帮助解决这个问题。我想我会发布它,因为它非常有用。

foreach (Item ThisItem in TheseItems)
{
    //Display properties of Item instance “ThisItem” (Excluded for ease of reading)
    ThisItem.Match()
            .Case<Computer>(comp => /* Do stuff with your computer */)
            .Case<Television>(tv => /* Do stuff with your television */)
            .Default(item => /* Do stuff with your item */);
}

实用程序类看起来像这样。下面给出了要点,而且扩展性很强。

public class Matcher<TMatch>
{
    private readonly TMatch _matchObj;
    private bool _isMatched;

    public Matcher(TMatch matchObj)
    {
        this._matchObj = matchObj;
    }

    public Matcher<TMatch> Case<TCase>(Action<TCase> action) where TCase : TMatch
    {
        if(this._matchObj is TCase)
        {
            this.DoCase(() => action((TCase)this._matchObj));
        }
        return this;
    }

    public void Default(Action<TMatch> action)
    {
        this.DoCase(() => action(this._matchObj));
    }

    private void DoCase(Action action)
    {
        if (!this._isMatched)
        {
            action();
            this._isMatched = true;
        }
    }
}

public static class MatcherExtensions
{
    public static Matcher<TMatch> Match<TMatch>(this TMatch matchObj)
    {
        return new Matcher<TMatch>(matchObj);
    }
}

【讨论】:

  • 就打我吧。我的答案是 DITTO。
  • 做同样事情的惯用方法是使用Computer computerItem = ThisItem as Computer; if (computerItem != null) { ... }。 is 操作符实际上执行了一个as 操作,然后检查它是否有null,因此执行is 后跟一个强制转换实际上需要额外的指令。
【解决方案2】:

这是我通常使用的方法。它可能比检查类型然后强制转换稍微快一些(我没有证据)。

foreach (Item ThisItem in TheseItems)
{
    //Display properties of Item instance “ThisItem” (Excluded for ease of reading)

    var computer = ThisItem as Computer;
    if (computer != null)
    {
         //Display distinct properties of Computer instance “ThisItem”
    }
}

【讨论】:

    【解决方案3】:

    告诉,不要问。

    不要向ThisItem 询问它的属性,这样你就可以编写它们,告诉它为你编写它们

    foreach (Item ThisItem in TheseItems)
    {
        ThisItem.DisplayProperties(Console.out);
    }
    

    然后,将DisplayProperties() 设为虚拟,并在Computer 中重载它以包含它独有的属性。

    【讨论】:

    • +1 这通常是这类问题的最佳答案,但并非总是如此。这甚至可能是 OP 的最佳答案。
    【解决方案4】:

    是的,就在您的 IF 子句中,强制转换为您的派生类并且属性将可用。

    foreach (Item ThisItem in TheseItems)
    {
        //Display properties of Item instance “ThisItem” (Excluded for ease of reading)
    
        if (ThisItem is Computer)
        {
           var ThisComputer = (Computer) ThisItem;
           Display(ThisComputer.CPU);
           //etc
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-15
      • 2017-05-07
      • 1970-01-01
      • 1970-01-01
      • 2018-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多