簡體   English   中英

C#根據類將項目從參數分配給變量

[英]C# Assigning items from params to variables based on class

我有一個問題,我將具有不同類但具有相同父類作為參數的多個項目傳遞給類構造函數,然后將它們分配給新類的變量:

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;
        }
    }
}

這導致編譯器說“無法將'Tool'隱式轉換為'Hammer',但是可以進行顯式轉換”。 在這種情況下可能是什么問題,並且可以通過一些簡單的方法解決?

每當您使用大量的case/switch ,都應將其作為警告信號, 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);
    }
}

問題是知道它是Hammer但是編譯器只知道它是Tool 如錯誤消息所述,解決此問題的方法是進行顯式轉換:

hammer = (Hammer)t;

通過這個轉換,您告訴編譯器t實際上是Hammer

你可以試試這個嗎? 此轉換操作可以為您提供預期的結果。 您可以訪問和使用derived class屬性

編輯答案並添加@ ja72推薦

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)
    {
        .......
    }
}

在現代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是一個布爾值,用於測試x是否屬於Hammer類型。 當用作if(x is Hammer y) { }如果x是一個Hammer式,它將被引用y變量的范圍之內if語句。

根據您的Toolbox類,似乎它最多可以包含1個錘子和1個螺絲刀。 暫時不要將變量定義為public; 您可以使用以下類定義獲得幾乎相同的效果:

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類添加新屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM