在字典中找不到c#对象
本文关键字:找不到 对象 字典 | 更新日期: 2023-09-27 18:13:16
我有一本字典。我使用下面的代码来获取对象的索引:
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;
但是它没有找到对象。我仔细检查了对象是否正确创建,是否存在,它确实存在!有问题的对象在"键"列中,我不想在"值"列中获得对象。
我也试过这段代码,它不能很好地工作:
type.Name = _shuffledClasses[new Classes()
{
Name = originName,
Namespace = type.Namespace
}].Name;
我的"Classes"对象如下所示:
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();
}
你的代码从根本上就被破坏了:
.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;
}
为什么找不到对象?
因为你没有在你的类中重写GetHashCode和Equals,这是它在Dictionary和HashSet中作为键所需的
Dictionary<TKey, TValue>
需要一个相等的实现来确定键是否相等。您可以通过使用接受比较器参数的构造函数来指定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
如果你使用的是Dictionary
,找到Key
的最清晰的方法是使用[]
或TryGetValue
。
使用linq是伟大的,但在我看来,这不是一个地方使用它。在字典中搜索key
是o(1)
操作,但使用linq的方式将其转换为o(n)
。如果您可以覆盖GetHashCode
和Equals
或提供自定义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();
}
}
方法重写实现的问题是:
= -在强制转换之后,您仍然没有实际比较属性
public override bool Equals(object obj) { Classes fooItem = obj as Classes; return fooItem == this; }
GetHashCode -你没有给它实现…仍然使用
object
的GetHashCode
public override int GetHashCode() { return base.GetHashCode(); }
更多参考参见:
- MSDN -实现Equals方法
- Stackoverflow -重写Equals()和GetHashCode()的正确方法
- Stackoverflow -为什么重要的是重写GetHashCode当Equals方法被重写?