【问题标题】:C# An item with the same key has already been addedC# 已添加具有相同键的项
【发布时间】:2015-08-21 07:41:10
【问题描述】:

即使我在添加之前检查地图是否已经包含密钥,我也会收到此错误..

if (ShortBuffer.ContainsKey(GetTuple(data))) return;
ShortBuffer.Add(GetTuple(data),                 <----- ERROR OCCURS HERE
    new Tuple<Timer, int, bool, Data>(
        new Timer(Convert.ToInt32(Ini.ReadValue("intervals", "clientbuffershort"))), 0, false, data));

GetTuple 方法:

private static Tuple<string, string, string> GetTuple(Data data)
{
    return new Tuple<string, string, string>(data.AucxisErrorId, data.ClientId, data.Area);
}

有什么想法吗?谢谢!

【问题讨论】:

  • 你的应用是多线程的吗...
  • 不,不是,这就是我不明白的原因
  • 那么我们需要代码来重现问题,以便回答您的​​问题。 (简短但完整的代码示例)
  • 您尝试使用ConcurrentDictionary 以确保它不是线程问题。
  • 这对您的问题并不重要,但您应该考虑将其取出 GetTuple(data) 并调用一次。我无法重现您的问题是单线程应用程序。一定有什么古怪的事情发生了。你的Data 结构是不可变的吗?是不是它在调用之间发生了变化(因为对属性的调用有副作用)?

标签: c# .net


【解决方案1】:

首先,每次调用 GetTuple 方法时都会返回一个新实例。它可能包含相同的数据,但它们仍然是不同的对象。所以我要做的第一步是将代码更改为:

var tuple = GetTuple(data);
if (ShortBuffer.ContainsKey(tuple)) return;

ShortBuffer.Add(tuple, new Tuple<Timer, int, bool, Data>(
    new Timer(Convert.ToInt32(Ini.ReadValue("intervals", "clientbuffershort"))), 0, false));

这可确保您至少比较并添加完全相同的对象到地图中。

其次确保 Tuple 类实现了IEquatable&lt;T&gt; 接口。这样,您可以确保比较 Tuple 对象的内容,而不是存储对象的内存地址(因为它们彼此不同)。更多关于如何实现IEquatable&lt;T&gt;接口的信息可以在这里找到:https://msdn.microsoft.com/en-us/library/ms131187(v=vs.110).aspx

【讨论】:

  • Tuple&lt;T1, T2, ...&gt; 是一个 .NET 类,无法更改。见here
  • 同意,现在我知道了;)。积极的一面是它已经实现了 IStructuralEquatable(它又派生自 IEquatable)。所以你在这里很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-29
  • 1970-01-01
  • 1970-01-01
  • 2021-05-14
  • 2017-08-20
相关资源
最近更新 更多