0

我正在为此争论不休。我想要一个哈希表(或字典......两者似乎都为此目的一样好)

我有一个具有 ItemNumber、Description 和 Quantity 的类 Item。我有一个要使用哈希表或字典的类 ItemCollection(当前使用 Item 数组)。在我的 Item 类中,我使用 ItemNumber 来比较 item a == item b。

所以我应该将 ItemNumber 移动到 ItemCollection 作为我的哈希表的键,还是应该离开它。我的一部分想要离开它,因为我生成了一个基于 Item 的表。但我的另一部分认为这是多余和愚蠢的。

我的最终目标是通过执行类似的操作来查看作为运送物品的 ItemCollection 是否等于另一个 ItemCollection(订单)。

foreach(var package in shipments)
    foreach(var item in package)
       shipOrder += item;

return mainOrder==shipOrder;

我希望这是有道理的。由于生病,我的头仍然有点模糊,所以我需要进一步澄清一些,请告诉我。

编辑

好的,所以我考虑了每个人所说的话,并尝试了它,大多数测试都通过了,除了一个,我不知道为什么。所以我会发布我所拥有的,看看你们是否能弄清楚我的愚蠢错误。

public class Item
{
    public Item(object[] array)
    {
        ItemNumber = array[0].ToString();
        Description = array[1].ToString();
        Quantity = (int)array[2];
    }
    public Item(string item, string desc, int qty)
    {
        ItemNumber = item;
        Description = desc;
        Quantity = qty;
    }
    /// <summary>
    /// </summary>
    public string ItemNumber;
    public string Description;
    public int Quantity;

    public override bool Equals(object obj)
    {
        //return compareTwoItems(this, (Item)obj);
        return this.GetHashCode() == obj.GetHashCode();
    }
    public static bool operator ==(Item ic1, Item ic2)
    {
        return compareTwoItems(ic1, ic2);
    }
    public static bool operator !=(Item ic1, Item ic2)
    {
        return !compareTwoItems(ic1, ic2);
    }
    private static bool compareTwoItems(Item ic1, Item ic2)
    {
        return (ic1.ItemNumber == ic2.ItemNumber)
            && (ic1.Quantity == ic2.Quantity);
    }
    public override int GetHashCode()
    {
        return ItemNumber.GetHashCode() ^ Quantity;
    }
}
public class ItemCollection : System.Collections.Generic.SortedDictionary<string, Item>
{
    public ItemCollection()
    {
    }
    public void AddItem(Item i)
    {
        this.Add(i.ItemNumber, i);
    }

    public string TrackNumber = "";
    /// <summary>
    /// Check to see if the Two ItemCollections have the same Quantity of items. If not it may be that the order was not completed
    /// </summary>
    /// <param name="obj">the sales order items</param>
    /// <returns>True if the quantity of the two collections are the same.</returns>
    /// <exception cref="ArgumentException">If the collections have different counts, or if ItemNumbers differ in one of the elements</exception>
    public override bool Equals(object obj)
    {
        return this.GetHashCode() == ((ItemCollection)obj).GetHashCode();
    }
    public override int GetHashCode()
    {
        int hash = 0;
        foreach (var item in this.Values)
            hash ^= item.GetHashCode();

        return hash;
    }
    /// <summary>
    /// Check to see if the Two ItemCollections have the same Quantity of items. If not it may be that the order was not completed
    /// </summary>
    /// <param name="ic1">the sales order items</param>
    /// <param name="ic2">the shipping ticket items</param>
    /// <returns>True if the quantity of the two collections are the same.</returns>
    /// <exception cref="ArgumentException">If the collections have different counts, or if ItemNumbers differ in one of the elements</exception>
    public static bool operator ==(ItemCollection ic1, ItemCollection ic2)
    {
        return ic1.Equals(ic2);
    }
    public static bool operator !=(ItemCollection ic1, ItemCollection ic2)
    {
        return !ic1.Equals(ic2);
    }
}

单元测试

    [TestMethod, TestCategory("ItemColl")]
    public void ItemCollectionPassTest()
    {
        MSSqlDatabase db = new MSSqlDatabase();
        ItemCollection salesOrder = db.GetItemsCollectionFromSalesOrder(4231);
        ItemCollection items = db.GetItemsCollectionFromSalesOrder(4231);

        Assert.AreEqual(salesOrder, items); //passes
        Assert.IsTrue(salesOrder == items); //passes
    }
    [TestMethod, TestCategory("ItemColl")]
    public void ItemCollectionDifferentQuantity()
    {
        MSSqlDatabase db = new MSSqlDatabase();
        ItemCollection salesOrder1 = db.GetItemsCollectionFromSalesOrder(4231);
        ItemCollection salesOrder2 = db.GetItemsCollectionFromSalesOrder(4232);
        Assert.AreNotEqual(salesOrder1, salesOrder2); //passes
        Assert.IsTrue(salesOrder1 != salesOrder2); //passes

        ItemCollection[] items = db.GetItemsCollectionFromShipping(4231);
        ItemCollection test = items[0];
        Assert.AreNotEqual(salesOrder1, test); //Fails
        CollectionAssert.AreNotEqual(salesOrder1, items[0]); // passes
    }

....现在由于某种原因它起作用了...我在项目中的 GetHash 方法中更改了我的代码中的一件事(忘记使用 ItemNumber 中的散列对数量进行异或),现在它们通过了...奇怪。但无论如何我都会发布我的代码,因为它可能会对某人有所帮助。

4

2 回答 2

1

我同意 Scarle88,我认为你ItemCollection应该扩展Dictionaryor Hashtable。字典将需要每个项目的唯一键,您可以为此使用项目编号(如果您的要求是每个项目都是唯一的)。

像这样:

public class Item {
    public string ItemNumber { get; set; }
    public string Description { get; set; }
    public string Quantity { get; set; }

    public override bool Equals(Object o) {
        // Implement your Equals here
    }
    public override int GetHashCode() {
        // Implement your hash code method here
    }
}

public class ItemCollection : Dictionary<string, Item> {
    public override bool Equals(Object o) {
        // Implement your collection's Equals method here
    }
}

我不确定您对比较收藏有什么要求。但是,如果您只想看到两个集合具有相同的项目,则可以这样实现ItemCollection.Equals

public override bool Equals(Object o) {
    if (o == null)
        return false;
    if (!(o is ItemCollection))
        return false;
    var other = o as ItemCollection;

    // check the 'this' collection
    foreach (var item in this.Keys) {
        if (item != null && !other.ContainsKey(item.ItemNumber))
            return false;

    // check the 'other' collection
    foreach (var item in other.Keys) {
        if (item != null && !this.ContainsKey(item.ItemNumber))
            return false;
    return true;
}
于 2012-12-06T21:06:00.443 回答
0

您可以使用 aHashTable<T>作为您的集合,并在您的 Item 类中覆盖基础对象Equals()GetHashCode()方法。

为什么在重写 Equals 方法时重写 GetHashCode 很重要?

于 2012-12-06T19:09:02.247 回答