使用先前从密钥集合中检索到的密钥时出现 KeyNotFoundException?

发布于 2024-08-18 12:44:28 字数 2952 浏览 6 评论 0原文

我有以下代码,由于某种原因,即使我使用的是我在上面检索到的几行的密钥,我也会收到 KeyNotFoundException 。有谁知道这不起作用的情况吗?我很困惑。顺便说一句,'SchemaElementType 是一个枚举。

public class DefaultValue
{
 private Dictionary<Parameter, string> _params;

 public DefaultValue(Dictionary<Parameter, string> parameters)
 {
        _params = parameters;
 }

  public string GetParameterValue(string name)
  {
      foreach(Parameter param in _params.Keys)
      {
           if(param.ParamName.Equals(name))
           {
               // **** Issue here  ****
               return _params[param];
           }
      }
      return string.Empty;
  }
}

[DataContract]
public class Parameter
    {
        #region Members
        private Guid _guid;
        private Guid _formulaGuid;
        private string _name;

        #endregion

        #region Constructor
        public Parameter(Guid guid, Guid formulaGuid, string name, SchemaElementType type)
        {
            ParamGuid = guid;
            FormulaGuid = formulaGuid;
            ParamName = name;
            ParamType = type;
        }

        public Parameter()
        {}

        #endregion

        #region Properties

        [DataMember]
        public Guid ParamGuid
        {
            get { return _guid; }
            set { _guid = value; }
        }

        [DataMember]
        public Guid FormulaGuid
        {
            get { return _formulaGuid; }
            set { _formulaGuid = value; }
        }

        [DataMember]
        public string ParamName
        {
            get { return _name; }
            set { _name = value; }
        }

        [DataMember]
        public SchemaElementType ParamType { get; set; }

        #endregion

        #region Overrides

        public bool Equals(Parameter other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            bool result =other._guid.Equals(_guid);
            result = result && other._formulaGuid.Equals(_formulaGuid);
            result = result && Equals(other._name, _name);
            result = result && Equals(other.ParamType, ParamType);

            return result;
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int result = _guid.GetHashCode();
                result = (result*397) ^ _formulaGuid.GetHashCode();
                result = (result*397) ^ (_name != null ? _name.GetHashCode() : 0);
                result = (result*397) ^ ParamType.GetHashCode();
                return result;
            }
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (Parameter)) return false;
            return Equals((Parameter) obj);
        }

        #endregion
    }

I've got the following code where for some reason I'm getting a KeyNotFoundException even though I'm using a key that I had retrived a couple of lines above. Does anyone know of a situation where this wouldn't work? I'm stumped. BTW 'SchemaElementType is an enum.

public class DefaultValue
{
 private Dictionary<Parameter, string> _params;

 public DefaultValue(Dictionary<Parameter, string> parameters)
 {
        _params = parameters;
 }

  public string GetParameterValue(string name)
  {
      foreach(Parameter param in _params.Keys)
      {
           if(param.ParamName.Equals(name))
           {
               // **** Issue here  ****
               return _params[param];
           }
      }
      return string.Empty;
  }
}

[DataContract]
public class Parameter
    {
        #region Members
        private Guid _guid;
        private Guid _formulaGuid;
        private string _name;

        #endregion

        #region Constructor
        public Parameter(Guid guid, Guid formulaGuid, string name, SchemaElementType type)
        {
            ParamGuid = guid;
            FormulaGuid = formulaGuid;
            ParamName = name;
            ParamType = type;
        }

        public Parameter()
        {}

        #endregion

        #region Properties

        [DataMember]
        public Guid ParamGuid
        {
            get { return _guid; }
            set { _guid = value; }
        }

        [DataMember]
        public Guid FormulaGuid
        {
            get { return _formulaGuid; }
            set { _formulaGuid = value; }
        }

        [DataMember]
        public string ParamName
        {
            get { return _name; }
            set { _name = value; }
        }

        [DataMember]
        public SchemaElementType ParamType { get; set; }

        #endregion

        #region Overrides

        public bool Equals(Parameter other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            bool result =other._guid.Equals(_guid);
            result = result && other._formulaGuid.Equals(_formulaGuid);
            result = result && Equals(other._name, _name);
            result = result && Equals(other.ParamType, ParamType);

            return result;
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int result = _guid.GetHashCode();
                result = (result*397) ^ _formulaGuid.GetHashCode();
                result = (result*397) ^ (_name != null ? _name.GetHashCode() : 0);
                result = (result*397) ^ ParamType.GetHashCode();
                return result;
            }
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (Parameter)) return false;
            return Equals((Parameter) obj);
        }

        #endregion
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小…红帽 2024-08-25 12:44:28

我担心 Parameter 是可变的。如果(将其添加到字典后)您更改了生成 GetHashCode() 时使用的任何值(即所有值),则所有投注均无效您保证会再次看到您的商品。我不会创建这些公共 setter,即

    [DataMember]
    public string ParamName // applies to all the properties, not just this one
    {
        get { return _name; }
        private set { _name = value; }
    }

Actaully,我可能会放弃显式字段并使用 C# 3.0 自动实现的属性:

    [DataMember]
    public string ParamName { get; private set; }

作为通过更改参数来中断的示例:

    var data = new Dictionary<Parameter, string>();
    Parameter p;
    data.Add((p = new Parameter(Guid.NewGuid(), Guid.NewGuid(), "abc",
        SchemaElementType.A)), "def");
    var dv = new DefaultValue(data);
    string val1 = dv.GetParameterValue("abc"); // returns "def"
    p.ParamGuid = Guid.NewGuid();
    string val2 = dv.GetParameterValue("abc"); // BOOM

作为最后的想法;如果典型的用法是通过string查找,那么为什么不使用名称作为内部字典的键呢?目前你还没有正确使用字典。

I worry about the fact that Parameter is mutable. If (after adding it to the dictionary) you have changed any of the values that are used when generating GetHashCode() (i.e. all of them) then all bets are off and you are not guaranteed to see your item again. I would not make these public setters, i.e.

    [DataMember]
    public string ParamName // applies to all the properties, not just this one
    {
        get { return _name; }
        private set { _name = value; }
    }

Actaully, I'd probably drop the explicit fields and use C# 3.0 automatically implemented properties:

    [DataMember]
    public string ParamName { get; private set; }

As an example that breaks by changing the parameter:

    var data = new Dictionary<Parameter, string>();
    Parameter p;
    data.Add((p = new Parameter(Guid.NewGuid(), Guid.NewGuid(), "abc",
        SchemaElementType.A)), "def");
    var dv = new DefaultValue(data);
    string val1 = dv.GetParameterValue("abc"); // returns "def"
    p.ParamGuid = Guid.NewGuid();
    string val2 = dv.GetParameterValue("abc"); // BOOM

As a final thought; if the typical usage is to lookup by string, then why not use the name as the key for the internal dictionary? At the moment you aren't using the dictionary properly.

仄言 2024-08-25 12:44:28

严格来说,您没有检索上面几行的(查找键),而是检索在某个时刻用于计算哈希键的对象。

当您插入字典时,将调用键对象的 GetHashKey 方法。如果从插入键值对到执行代码的时间发生变化,您将得到所描述的行为。 (除非 GetHashKey no 返回一个与不同键值对的键匹配的值,在这种情况下,您会得到非常奇怪的行为而不是例外)

我会在插入和检索时查找哈希键的值看看它们之间是否存在不匹配

Well strictly speaking you're not retrieving the (lookup key) a few lines above you are retreiving an object that at some point was used for calculating the hash key.

When you insert into a Dictionary the GetHashKey method of the key object will be called. If that changes from the time you insert the key-value pair to the time your code is executed you will get the described behaviour. (unless of cause if the GetHashKey no returns a value matching a key to a different key-value pair, in that case you get really weird behaviour not an exception)

I'd look for the value of the hash key when inserting and when retreiving and see if there's a mismatch between them

何处潇湘 2024-08-25 12:44:28

您可以利用 KeyValuePair<>班级:

foreach(var item in _params)
{
   if(item.Key.ParamName.Equals(name))
   {
      return item.Value;
   }
}

You can take advantage of the KeyValuePair<> class:

foreach(var item in _params)
{
   if(item.Key.ParamName.Equals(name))
   {
      return item.Value;
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文