1

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

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

在执行此操作时,我还想显示计算机的不同属性(例如 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”
}

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

4

4 回答 4

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);
    }
}
于 2013-06-27T20:16:41.617 回答
1

告诉,不要问。

不要询问ThisItem它的属性,以便您可以编写它们,告诉它为您编写它们

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

然后,创建DisplayProperties()虚拟,并重载它Computer以包含它独有的属性。

于 2013-06-27T21:55:46.817 回答
1

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

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”
    }
}
于 2013-06-27T20:20:29.190 回答
0

是的,就在您的 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
    }
}
于 2013-06-27T20:16:26.913 回答