C#根据类将params中的项目分配给变量

时间:2018-04-08 22:15:24

标签: c# class inheritance parameters

我遇到了一个问题,我将多个项目传递给不同的类,但是同一个父类作为类构造函数的params,然后将它们分配给新类的变量:

public class Tool {}
public class Hammer:Tool {}
public class Screwdriver:Tool{}

所以我的工具类都继承自父工具类。现在我想创建一个工具箱,我存储我的工具;但是,我不会总是想用一套完整的工具制作它,所以我传递了一个参数数量未定义的参数:

public class Toolbox{
public Hammer hammer;
public Screwdriver screwdriver;
public Toolbox(params Tool[] tool){
    foreach (Tool t in tool){
        switch (t.getType().Name){
            case "Hammer":
                hammer = t;
                break;
            case "Screwdriver":
                screwdriver = t;
                break;
        }
    }
}

这会导致编译器说它不能隐式转换'工具' to' Hammer',但可以使用显式转换"。 在这种情况下可能出现什么问题,是否有可能以一种简单的方式解决?

5 个答案:

答案 0 :(得分:2)

每当你使用大量case/switch时,你应该把它当作一个警告标志,表明你没有按照OO的方式做事。

执行此操作的OO方法是为Tool定义公共属性,并在选择插槽时仅使用该属性。然后在子类中设置位置,如下所示:

Enum Location { Big, Large, Small, Drawer, Hanging}

class Tool
{
    public abstract Location Location { get; }
}

class Hammer
{
    public override Location { get { return Location.Top; } }
}

现在您的工具箱代码很简单:

class Toolbox
{
    public readonly List<Location,List<Tool>> Store = new List<Location,List<Tool>>();

    public Toolbox(params Tool[] tool)
    {
        foreach (Tool t in tool)
            this.Store[t.Location].Add(t);
    }
}

如果你需要更多的复杂性,可以将逻辑放入后代类中:

class Tool
{
    public abstract void StoreIn(Toolbox toolbox);
}

class Hammer
{
    public override void StoreIn(Toolbox toolbox)
    {
        toolbox.TopDrawer.Add(this);
    }
}

同样,您的工具箱代码很简单:

class Toolbox
{
    public void AddTools(params Tool[] tool)
    {
        foreach (Tool t in tool) t.StoreIn(this);
    }
}

答案 1 :(得分:1)

问题是知道它是Hammer,但编译器只知道它是Tool。正如错误消息所说,解决这个问题的方法是使用显式转换:

hammer = (Hammer)t;

通过此演员,您告诉编译器t实际上是Hammer

答案 2 :(得分:1)

你能试试吗?此演员操作可以为您提供预期的结果。您可以访问并使用derived class属性

编辑回答并添加了@ ja72 recomendation

foreach (Tool t in tool)
{
    // option 1
    if (t is Hammer)
    {
        Hammer hammer = t as Hammer;
        .....
    }

    // option 2 @ja72 recomendation
    if (t is Screwdriver screwdriver)
    {
        .......
    }
}

答案 3 :(得分:0)

在现代C#中,您可以检查类型:

public class Toolbox
{
    readonly Hammer hammer;
    readonly Screwdriver screwdriver;
    public Toolbox(params Tool[] tool)
    {
        foreach (Tool t in tool)
        {
            if (t is Hammer hammer)
            {
                this.hammer = hammer;
            }
            if (t is Screwdriver screwdriver)
            {
                this.screwdriver = screwdriver;
            }
        }
    }
#region Properties       
    public Screwdriver Screwdriver => screwdriver;
    public Hammer Hammer => hammer;
    public bool HasHammer => hammer != null;
    public bool HasScrewdriver => screwdriver != null;
#end region
}

构造x is Hammer是一个布尔值,用于测试xHammer类型。如果if(x is Hammer y) { }x类型,则用作Hammer时,y语句范围内的if变量将引用它。

答案 4 :(得分:0)

根据您的Toolbox类,它最多可以包含1个Hammer和最多1个Screwdriver。让我们忽略你将变量定义为公共的那一刻;您可以使用以下类定义获得几乎相同的效果:

public class Toolbox {
  public Hammer Hammer { get; set;}
  public Screwdriver Screwdriver { get; set;}
  public Toolbox() { }
}

然后而不是写(假设你已经定义了一个名为hammer的变量):

Toolbox t = new Toolbox(hammer);

你可以写:

Toolbox t = new Toolbox() { Hammer = hammer };

如果您需要添加其他工具,只需向Toolbox类添加新属性即可。