2010-01-19 136 views
1

我得到了下面的代码,因为某些原因,我得到了一个KeyNotFoundException,即使我使用了一个我已经回顾了上面几行的密钥。有人知道这种情况不适用吗?我很难过。顺便说一句'SchemaElementType是一个枚举。使用先前从密钥集中检索的密钥时,获取KeyNotFoundException?

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 
    } 
+0

你有一些实际上显示问题的代码吗? – 2010-01-19 12:32:06

回答

0

您可以乘坐KeyValuePair <>类的优势时:

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

hmm,var abuse :)我会坚持使用KeyValuePair <参数,字符串>,因为var应该只在你不知道类型时使用(按照C#参考),但我想那是另一个辩论发生在其他地方:) – Wayne 2010-01-19 12:15:51

+2

@Wayne - 这显然是一个主观点,但什么额外的信息会告诉你?为什么混淆代码?国际海事组织的'var'使用情况非常明确,可以在此处接受 – 2010-01-19 16:26:31

+0

我已经标记了这个答案,因为它帮助我修复了错误(时间紧),虽然我已经给Mark和Rune FS投票了,因为他们都强调需要改进Parameter类的编码/使用它作为关键。我将尽快介绍这些变化。多谢你们。 – 2010-01-19 16:27:24

1

严格来说,您不会检索(查找键)上面的几行,而是在某个点上用于计算散列键的对象。

当您插入字典时,将调用密钥对象的GetHashKey方法。如果从插入键值对到执行代码的时间发生变化,您将获得所描述的行为。 (除非如果GetHashKey否返回一个值匹配不同的键值对的键值,那么你真的很奇怪的行为不是例外)

我会寻找哈希键值插入和retreiving,看看是否有他们之间的不匹配

+0

从你的类型变化..应该不是时间?我相信那是你的意思? – Wayne 2010-01-19 12:07:48

+0

@Wayne你纠正了,我做了更改tu – 2010-01-20 17:57:39

2

我担心的事实,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来查找,那么为什么不将该名称用作内部字典的关键字?目前你没有正确使用字典。

+0

我很确定参数键在添加和获取之间完全没有改变,但我会检查。我只是从别人那里拿起代码,所以还没有完全意识到它的用途。完全同意你对实现的想法,只需访问进行更改的影响。 – 2010-01-19 15:27:34