2

各アイテムがアイテムの配列を保持できるプログラムに取り組んでいます(ツリーのような構造のメニューを作成しています)

現在、配列ではなくリストとしてアイテムを持っていますが、コードを単純化するためにそれを最大限に活用しているとは思えません。インターフェイス(.add、.removeなど)が非常に理にかなっているため、標準の配列ではなくリストを選択しました。

構造を検索して名前のパス(つまり、Item.subitem.subsubitem.subsubsubitem)を返すコードがあります。以下は私のコードです:

public class Item
{
                                                                //public Item[] subitem; <-- Array of Items
    public List<Item> subitem;                                  // <-- List of Items

    public Color itemColor = Color.FromArgb(50,50,200);
    public Rectangle itemSize = new Rectangle(0,0,64,64);
    public Bitmap itemBitmap = null;
    public string itemName;


    public string LocateItem(string searchName)
    {
        string tItemName = null;

        //if the item name matches the search parameter, send it up)
        if (itemName == searchName)
        {
            return itemName;
        }

        if (subitem != null)
        {

            //spiral down a level
            foreach (Item tSearchItem in subitem)
            {
                tItemName = tSearchItem.LocateItem(searchName);

                if (tItemName != null)
                    break;  //exit for if item was found
            }
        }


        //do name logic (use index numbers)
        //if LocateItem of the subitems returned nothing and the current item is not a match, return null (not found)
        if (tItemName == null && itemName != searchName)
        {
            return null;
        }

        //if it's not the item being searched for and the search item was found, change the string and return it up
        if (tItemName != null && itemName != searchName)
        {
            tItemName.Insert(0, itemName + ".");  //insert the parent name on the left -->  TopItem.SubItem.SubSubItem.SubSubSubItem
            return tItemName;
        }

        //default not found
        return null;
    }


}

私の質問は、リストでこれを行う簡単な方法があるかどうかです。リストを使うべきか、配列だけを使うべきかについて、頭の中で行ったり来たりしてきました。リストがある唯一の理由は、アイテムを追加または削除するたびに配列のサイズを変更するコードを作成する必要がないようにするためです。

4

3 に答える 3

2

この場合、リストを使用することは完全に許容されます。パフォーマンスが問題である場合は、アレイの方が適しています。問題がある場合、アレイはわずかに高速ですが、発見したように柔軟性がはるかに低くなります。

人々が十分に話していないことの1つは、単純さがコードを構造化するための優れた基盤であるということです。配列よりもリストを使用して記述および保守する方が簡単な場合は、リストを使用することは(他のすべてが等しい)完全に正しいことです。

于 2012-09-03T03:14:37.473 に答える
2

リストは素晴らしいですね。ただし、定義のバリエーションをお勧めします。次のようにクラスを作成してみてください。

public class Item : List<Item>
{
    public string Name;
}

Item継承を作成するList<Item>と、フィールドを必要とせずに自動的にツリーになりsubitemます。

これがあなたのクラスの私のフルバージョンです:

public class Item : List<Item>
{
    public string Name;

    private List<Item> LocateItems(string searchName)
    {
        if (this.Name == searchName)
            return (new [] { this }).ToList();

        var result =
            this
                .Select(s => s.LocateItems(searchName))
                .Where(x => x !=null && x.Count > 0)
                .FirstOrDefault();

        if (result != null)
            result.Add(this);

        return result;
    }

    public string LocateItem(string searchName)
    {
        var items = this.LocateItems(searchName);
        if (items == null)
            return null;
        else
            return String.Join(".", items.Select(i => i.Name).Reverse());
    }
}

このメソッドは、一致したものから始まり、ルートまでのすべての親インスタンスが続くLocateItemsリストを返します。ItemItemItem

私はこのコードでテストしました:

var foos = new Item() { Name = "Foo" };
var bars = new Item() { Name = "Bar" };
var qazs = new Item() { Name = "Qaz" };
var wees = new Item() { Name = "Wee" };

foos.Add(bars);
bars.Add(qazs);
foos.Add(wees);

Console.WriteLine(foos.LocateItem("Wee"));
Console.WriteLine(foos.LocateItem("Qaz"));
Console.WriteLine(foos.LocateItem("Bar"));
Console.WriteLine(foos.LocateItem("Foo"));

そして、私はこれらの結果を得ました:

Foo.Wee
Foo.Bar.Qaz
Foo.Bar
Foo
于 2012-09-03T04:53:01.427 に答える
1

リストをお勧めします。配列へのアイテムの追加/削除はメモリを再割り当てするため、アイテムの動的コレクション(私があなたの場合だと思います)の場合、リストは通常​​、全体的にパフォーマンスが向上します。あなたは一見したいかもしれません:

配列とリスト<T>:いつどちらを使用するか?

于 2012-09-03T03:35:26.020 に答える