Please read my previous question, because my fear of getting collision when using hashCode for strings ! Previous question
I having a database table with items in a repo, and a "incoming" function with items from a model that should sync - to the database table.
Im using intersect and except to make this possible.
The class i use for my sunc purpose:
private class syncItemModel
{
public override int GetHashCode()
{
return this.ItemLookupCode.GetHashCode();
}
public override bool Equals(object other)
{
if (other is syncItemModel)
return ((syncItemModel)other).ItemLookupCode == this.ItemLookupCode;
return false;
}
public string Description { get; set; }
public string ItemLookupCode { get; set; }
public int ItemID { get; set; }
}
Then i use this in my method: 1) Convert datatable items to syncmodel:
var DbItemsInCampaignDiscount_SyncModel =
DbItemsInCampaignDiscount(dbcampaignDiscount, datacontext)
.Select(i => new syncItemModel { Description = i.Description,
ItemLookupCode = i.ItemLookupCode,
ItemID = i.ID}).ToList();
2) Convert my incoming item model to syncmodel:
var ItemsInCampaignDiscountModel_SyncModel = modelItems
.Select(i => new syncItemModel { Description =
i.Description, ItemLookupCode = i.ItemLookUpCode, ItemID =0 }).ToList();
3) Make an intersect:
var CommonItemInDbAndModel =
ItemsInCampaignDiscountModel_SyncModel.Intersect(DbItemsInCampaignDiscount_SyncModel).ToList();
4) Take out items to be deleted in database (that not exist in incoming model items)
var SyncModel_OnlyInDb =
DbItemsInCampaignDiscount_SyncModel.Except(CommonItemInDbAndModel).ToList();
5) Take out items to be added to database, items that exist in incoming model but not in db:
var SyncModel_OnlyInModel =
ItemsInCampaignDiscountModel_SyncModel.Except(CommonItemInDbAndModel).ToList();
My question is then - can it be a collision? Can two differnt ItemLookupCode in my example be treated as the same ItemLookupCode? Because intersect and except using HashCode ! Or vill the Equal function "double check" it -so this approach is safe to use? If its a possible chance of collision how big is that chance?
Yes, there could be always a hash-collision, that's why identity should be confirmed by calling Equals()
. GetHashCode() and Equals() must be implemented correctly.
Except()
in LINQ to Objects internally uses HashSet
, in case of hash-collision it will call Equals to guarantee identity. As you are using a single property, you are good to proxy calls to its hashcode and equals methods.
Please find some comments below about your implementation:
This is fine to compare strings with ==, but if type is changed to non-primitive, you'll get issues because object reference instead of content will be compared. Proxy call to Equals()
instead of ==
.
That is very error prone to bound gethashcode/Equals logic to mutable state. I'd strongly recommend to encapsulate your state so that once you create your object it could not be changed, make set
private for a sake of safety.