我有一本词典。我使用此代码来获取对象的索引:
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;
但它没有找到对象。我仔细检查了对象是否正确创建,是否存在,它确实存在!有问题的对象位于' Key'我不希望将这个对象放入' Value'列。
我也尝试了这段代码,但这些代码并不起作用:
type.Name = _shuffledClasses[new Classes()
{
Name = originName,
Namespace = type.Namespace
}].Name;
我的"课程"对象如下所示:
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();
}
答案 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很棒,但在我看来,这不是一个使用它的地方。在字典中搜索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 - 您没有给它实现..仍在使用GetHashCode
的{{1}}
object
如需进一步参考,请参阅: