2016-10-15 14 views
0

私は辞書を持っています。このコードを使ってオブジェクトのインデックスを取得します:C#辞書に辞書が見つかりません<T, T>

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; 

しかし、オブジェクトは見つかりません。私は、オブジェクトが正しく作成されているかどうか、そしてそれが存在するかどうかを再度チェックします。対象のオブジェクトは「キー」列にあり、「値」列でオブジェクトを取得することはできません。

私はaswell動作しない、また、コードのこの部分を試してみました:次のように

type.Name = _shuffledClasses[new Classes() 
{ 
    Name = originName, 
    Namespace = type.Namespace 
}].Name; 

私の「クラス」オブジェクトが見えます:

class Classes 
{ 
    public string Namespace { get; set; } 
    public string Name { get; set; } 
} 

なぜ文句を言わない、それは、オブジェクトを見つけますか?

今私のクラスは次のようになりますし、まだ動作しません、私はいくつかの研究を行なったし、私が等しく、GetHashCodeメソッドをオーバーライドしてみました:

public override bool Equals(object obj) 
{ 
    Classes fooItem = obj as Classes; 
    return fooItem == this; 
} 

public override int GetHashCode() 
{ 
    return base.GetHashCode(); 
} 
+0

あなたは終わっていませんでしたのでクラス内で 'GetHashCode'と' Equals'を乗ります。これは 'Dictionary'と' HashSet'のキーとして動作するために必要です。 – MarcinJuraszek

+0

@MarcinJuraszek 2番目のバージョンを使用する場合も、Equalsをオーバーライドする必要がありますか? – ioncodes

+0

2番目のバージョンは 'GetHashCode' /' Equals'実装を必要とするバージョンです。 – MarcinJuraszek

答えて

3

あなたのコードは基本的に右ここ壊れている:

.GetEnumerator().Current.Name; 

列挙子は、先にMoveNext()またはCurrentで1つの要素を移動する必要があります。

また、列挙子を配置する必要があります。代わりにこれを試してみてください:

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

私はこれを前に考えていたので、別の解決策を試しました。第2版​​の考えは? – ioncodes

+0

コードの最後の部分がうまくいきました! – ioncodes

+0

ようこそ。それにもかかわらず、キーで辞書の値を調べるには、MarcinとGiladのようにキークラスを適切にする必要があります。 – Lucero

2

なぜ?

あなたがGetHashCodeメソッドをオーバーライドして、クラス内のequals、それは辞書でキーとして動作するために必要とされるとHashSetの

なかったので

Dictionary<TKey, TValue>キーが等しいかどうかを判断するために平等の実装が必要です。比較器パラメータを受け入れるコンストラクタを使用して、IEqualityComparer<T>汎用インターフェイスの実装を指定できます。 実装を指定しない場合は、デフォルトの汎用同値比較器EqualityComparer<T>.Defaultが使用されます。タイプTKeySystem.IEquatable<T>汎用インターフェースを実装している場合、デフォルトの等価比較プログラムはその実装を使用します。

そして、このタイプの汎用型比較器では、タイプにIEquatable<T>が実装されていない場合、参照の等価性が使用されます。

カスタム平等を実装したくない場合は、LINQとFirstを使用してみてくださいすることができますが、その値を取得するには、コレクション全体をスキャンする必要がありますので、それはDictionary<TKey, TValue>を使用しての目的を打ち負かす:

shuffledClasses.First(x => x.Key.Name == myName && x.Key.Value == myValue).Value 
+0

あなたはその情報をどこで見つけましたか?私にとっては、 'Key'はカスタム' Classes'クラスのようです。 – MarcinJuraszek

+0

はい、そうです。最初のバージョンの後にコードを読み終えました。ごめんなさい :) – Lucero

2

を使用している場合は、またはTryGetValueを使用して、を見つける最も分かりやすい方法です。

linqの使用は素晴らしいですが、私の意見ではこれを使用する場所ではありません。辞書内のkeyを検索すると、o(1)の操作になりますが、linqを使用すると、o(n)になります。 GetHashCodeEqualsを無効にするか、カスタム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(); 
    } 
} 

メソッドのオーバーライドの実装に問題がある:

  1. 等しい - 鋳造後のあなたはまだ実際に

    public override bool Equals(object obj) 
    { 
        Classes fooItem = obj as Classes; 
        return fooItem == this; 
    } 
    
  2. 特性を比較していませんGetHashCode - あなたは実装しませんでした..まだのGetHashCodeを使用してさらに参照の場合

    public override int GetHashCode() 
    { 
        return base.GetHashCode(); 
    } 
    

参照:

  1. MSDN - Implementing the Equals Method
  2. のStackOverflow - Correct way to override Equals() and GetHashCode()
  3. のStackOverflow - Why is it important to override GetHashCode when Equals method is overridden?