1

我有以下对象,我想要一个字典来有条件地确定是否有重复。例如,在一本字典中,我只关心两个属性对于我的键来说是唯一的。在第二个字典中,我希望所有属性对于键都是唯一的。

问题一:

我应该覆盖哪些接口来完成此操作?(例如 GetHashCode、IEqualityComparer、equals 运算符)

问题2:

如果我更改了最终会更改键值的属性,我该怎么办?如果我做一个字典,这可能更相关,因为 .NET 框架以某种方式为我处理了这个问题,但我从来没有想过。

代码

public class EventData : IEqualityComparer<EventData>
{
    public string ComputerName { get; set; }
    public Guid? CategoryName { get; set; }
    public string LogName { get; set; }
    public int EventID { get; set; }
    public long? EventUniqueTracker { get; set; }

    public DateTime LastQueryDate { get; set; }
    public DateTime? DateOfRecord { get; set; }

    //public int QueryCount { get; set; }
    public int QueryCount = 0 ;//

    public string  zData { get; set; }

    public EventData(string computerName, Guid? categoryName, string logName, int eventID, long? eventUniqueTracker, int queryCount)
    {
        ComputerName = computerName;
        CategoryName = categoryName;
        LogName = logName;
        EventID = eventID;
        EventUniqueTracker = eventUniqueTracker;

        LastQueryDate = DateTime.Now;
        QueryCount = queryCount;
    }

    public EventData()
    {
    }

    public override int GetHashCode()
    {
        return GetHashCode(HashType.ZCompCatLogEventAllData);
    }
    public object GetString(HashType hType)
    {
        switch (hType)
        {
            case HashType.AComputerName:
                return ComputerName;
                break;
            case HashType.BCompAndCat:
                return new { A = ComputerName, B = CategoryName };
                break;
            case HashType.CCompCatLog:
                return new { A = ComputerName, B = CategoryName, C = LogName };
                break;
            case HashType.DCompCatLogEvent:
                return new { A = ComputerName, B = CategoryName, C = LogName, D = EventID };
                break;
            case HashType.ECompCatLogEventUserDefined1:
            case HashType.FCompCatLogEventUserDefined2:
            case HashType.ZCompCatLogEventAllData:
                return new { A = ComputerName, B = CategoryName, C = LogName, D = EventID, E = EventUniqueTracker };
            default:
                break;
        }
        return new object { };
    }

    public int GetHashCode(HashType hType)
    {
        return GetString(hType).GetHashCode();
        return 1;
    }

    public override string ToString()
    {
        return ComputerName + " " + CategoryName + " " + LogName + " " + EventID + " " + EventUniqueTracker;
    }

    public bool Equals(EventData x, EventData y)
    {
        return x.ComputerName == y.ComputerName &&
               x.CategoryName == y.CategoryName &&
               x.LogName == y.LogName &&
               x.EventID == y.EventID &&
               x.EventUniqueTracker == y.EventUniqueTracker;
    }

    public int GetHashCode(EventData obj)
    {
        EventData ci = (EventData)obj;
        // http://stackoverflow.com/a/263416/328397
        return new { A = ci.ComputerName, B = ci.CategoryName, C = ci.LogName, D = ci.EventID, E = ci.EventUniqueTracker }.GetHashCode();
    }
}
4

1 回答 1

2

听起来您应该实施IEqualityComparer<EventData>- 但不是在其内部EventData。创建两个单独的实现 - 一个用于第一个相等概念,一个用于第二个。然后将您的字典创建为:

var first = new Dictionary<EventData, string>(new PartialDataEqualityComparer());
var second = new Dictionary<EventData, string>(new FullDataEqualityComparer());

或者,也许您想将第二种情况视为 的“自然”相等EventData,在这种情况下,您可以在创建第二个字典时EventData实现IEquatable<EventData>而不指定比较器。

基本上,您实现IEquatable<T>说“这种类型的实例能够将自身与”的实例进行比较,T而您实现IEqualityComparer<T>说“这种类型的实例能够比较T”的任何两个实例。

如果我更改了最终会更改键值的属性,我该怎么办?

基本上,你已经吃饱了。您将不会(或至少可能不会)能够在您的字典中再次找到该键。您应该尽可能小心地避免这种情况。就我个人而言,我通常发现作为字典键的良好候选者的类也是不变性的良好候选者。

于 2012-05-22T19:39:03.847 回答