Reputation: 2409
I'm debating back and forth about this. I want to have a Hashtable (or dictionary... both seem to do just as good for this purpose)
I have a class Item which has ItemNumber, Description, and Quantity. I have a class ItemCollection (which currently uses a Item array) that I want to use either a hashtable or dictionary. In my Item class I use the ItemNumber to compare if item a == item b.
So should I move ItemNumber up to ItemCollection as the Key for my hashtable or should I just leave it. Part of me wants to leave it since I generate a table based on Item.. But another part of me thinks that is redundant and silly.
What my end goal is to see if a ItemCollection which is the items shipped equals another ItemCollection (the order) by doing something like this.
foreach(var package in shipments)
foreach(var item in package)
shipOrder += item;
return mainOrder==shipOrder;
I hope this makes sense. My head is still a little foggy from being sick, so I f i need to clarify some more please let me know.
EDIT
ok so I thought about what everyone said, and tried it, and most of tests pass except for one, and i can't figure out why. So i'll post what I have and see if you guys can figure out my stupid mistake.
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);
}
}
Unit Tests
[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
}
.... and now for some reason it works... I changed one thing in my code in teh GetHash Method in Item (forgot to xor the quantity with the hash from the ItemNumber) and now they pass... weird. but i'll post my code anyway as it might help someone.
Upvotes: 0
Views: 402
Reputation: 3985
I agree with scarle88, I think your ItemCollection
should extend Dictionary
or Hashtable
. The dictionary is going to need a unique key for each item, and you could use the item number for that (if your requirements are that each item is unique).
Like this:
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
}
}
I'm not sure what your requirements are for comparing the collections. But if you only care to see that both collections have the same items, you could implement ItemCollection.Equals
like this:
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;
}
Upvotes: 1
Reputation: 1955
You could use a HashTable<T>
as your collection and in your Item class override the base object Equals()
and the GetHashCode()
methods.
Why is it important to override GetHashCode when Equals method is overridden?
Upvotes: 0