2010-01-19 139 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