在Dictionary <t,t =“”>中找不到C#对象

时间:2016-10-15 17:59:54

标签: c# dictionary

我有一本词典。我使用此代码来获取对象的索引:

type.Name = _shuffledClasses.Where(entry => entry.Key.Name.Equals(originName))
                            .Where(entry => entry.Key.Namespace.Equals(type.Namespace))
                            .Select(item => item.Value).GetEnumerator().Current.Name;

但它没有找到对象。我仔细检查了对象是否正确创建,是否存在,它确实存在!有问题的对象位于&#39; Key&#39;我不希望将这个对象放入&#39; Value&#39;列。

我也尝试了这段代码,但这些代码并不起作用:

type.Name = _shuffledClasses[new Classes()
{
     Name = originName,
     Namespace = type.Namespace
}].Name;

我的&#34;课程&#34;对象如下所示:

class Classes
{
    public string Namespace { get; set; }
    public string Name { get; set; }
}

为什么不找对象?

我做了一些研究,我尝试重写Equals和GetHashCode,现在我的班级看起来像这样但仍然无法运作:

public override bool Equals(object obj)
{
    Classes fooItem = obj as Classes;
    return fooItem == this;
}

public override int GetHashCode()
{
    return base.GetHashCode();
}

3 个答案:

答案 0 :(得分:3)

你的代码从根本上被打破了:

.GetEnumerator().Current.Name;

枚举器需要使用MoveNext()向前移动一个元素,否则Current将没有任何值。

此外,应该处理调查员。试试这个:

type.Name = _shuffledClasses.Where(entry => entry.Key.Name.Equals(originName))
                            .Where(entry => entry.Key.Namespace.Equals(type.Namespace))
                            .Select(item => item.Value)
                            .First().Name;

如果您因任何原因不想使用First(),也可以像这样手动迭代:

using (var enumerator = _shuffledClasses.Where(entry => entry.Key.Name.Equals(originName))
                            .Where(entry => entry.Key.Namespace.Equals(type.Namespace))
                            .Select(item => item.Value).GetEnumerator()) {
    enumerator.MoveNext(); // maybe check here if the operation is successful!
    type.Name = enumerator.Current.Name;
}

答案 1 :(得分:2)

  

为什么不找对象?

因为你没有覆盖你的类中的GetHashCode和Equals,这是它​​在Dictionary和HashSet中作为键所必需的

  

Dictionary<TKey, TValue>需要一个相等的实现来确定密钥是否相等。您可以使用接受comparer参数的构造函数指定IEqualityComparer<T>泛型接口的实现; 如果您未指定实现,则使用默认的通用相等比较器EqualityComparer<T>.Default 。如果类型TKey实现System.IEquatable<T>通用接口,则默认的相等比较器使用该实现。

如果您的类型未实现IEquatable<T>,则此通用比较器使用引用相等。

如果您不想实现自定义相等性,可以尝试使用LINQ和First,但这样做会失败使用Dictionary<TKey, TValue>的目的,因为您必须将整个集合扫描到得到那个价值:

shuffledClasses.First(x => x.Key.Name == myName && x.Key.Value == myValue).Value

答案 2 :(得分:2)

如果您使用的是Dictionary,则可以使用Key[]找到TryGetValue的最清晰方式。

使用linq很棒,但在我看来,这不是一个使用它的地方。在字典中搜索keyo(1)操作,但使用linq的方式将其转换为o(n)。如果您可以覆盖GetHashCodeEquals或提供自定义IEquatable<>,我认为它会更好。

static void Main(string[] args)
{
    Dictionary<Classes, string> data = new Dictionary<Classes, string>
    {
        [new Classes { Name = "a", Namespace = "a" }] = "first",
        [new Classes { Name = "b", Namespace = "b" }] = "second",
    };

    var key = new Classes { Name = "a", Namespace = "a" };

    string result1 = data[key]; // "first"


    string result2;
    if (data.TryGetValue(key, out result2))
    {
        Console.WriteLine(result2); // 'first"
    }
}

class Classes
{
    public string Name { get; set; }
    public string Namespace { get; set; }

    public override bool Equals(object obj)
    {
        var other = obj as Classes;
        if (other == null)
            return false;

        return other.Name == Name &&
               other.Namespace == Namespace;
    }

    public override int GetHashCode()
    {
        return Name.GetHashCode() ^
               Namespace.GetHashCode();
    }
}

执行覆盖方法的问题是:

  1. 等于 - 投射后你仍然没有实际比较属性

    public override bool Equals(object obj)
    {
        Classes fooItem = obj as Classes;
        return fooItem == this;
    }
    
  2. GetHashCode - 您没有给它实现..仍在使用GetHashCode的{​​{1}}

    object
  3. 如需进一步参考,请参阅:

    1. MSDN - Implementing the Equals Method
    2. Stackoverflow - Correct way to override Equals() and GetHashCode()
    3. Stackoverflow - Why is it important to override GetHashCode when Equals method is overridden?