2012-03-11 10 views
0

は、私は2つのコレクションが等価であるかどうかをテストするために拡張メソッドを作成C#ジェネリック型引数をより簡潔に表現しますか?

Comparing two collections for equality irrespective of the order of items in them

触発します。拡張メソッドを使用するには、私はこのような2種類のパラメータを指定する必要があります。

IsEquivalentToTestHelper<ObservableCollection<string>, string>(first, second, true); 

を一つだけの一般的な制約(例えばObservableCollection<string>)を指定する必要がなるように拡張メソッドを実装する方法はありますか?

更新:この修正プログラムには、回答に基づいてadditional responseという名前が付けられています。

はここに私の元のコードです:

static public class EnumerableExtensions 
{ 
    static public bool IsEquivalentTo<E,T>(this E first, E second) where E : IEnumerable<T> 
    { 
     if ((first == null) != (second == null)) 
      return false; 

     if (!object.ReferenceEquals(first, second) && (first != null)) 
     { 
      if (first.Count() != second.Count()) 
       return false; 

      if ((first.Count() != 0) && HaveMismatchedElement<E,T>(first, second)) 
       return false; 
     } 

     return true; 
    } 

    private static bool HaveMismatchedElement<E,T>(E first, E second) where E : IEnumerable<T> 
    { 
     int firstCount; 
     int secondCount; 

     var firstElementCounts = GetElementCounts<E,T>(first, out firstCount); 
     var secondElementCounts = GetElementCounts<E,T>(second, out secondCount); 

     if (firstCount != secondCount) 
      return true; 

     foreach (var kvp in firstElementCounts) 
     { 
      firstCount = kvp.Value; 
      secondElementCounts.TryGetValue(kvp.Key, out secondCount); 

      if (firstCount != secondCount) 
       return true; 
     } 

     return false; 
    } 

    private static Dictionary<T, int> GetElementCounts<E,T>(E enumerable, out int nullCount) where E : IEnumerable<T> 
    { 
     var dictionary = new Dictionary<T, int>(); 
     nullCount = 0; 

     foreach (T element in enumerable) 
     { 
      if (element == null) 
      { 
       nullCount++; 
      } 
      else 
      { 
       int num; 
       dictionary.TryGetValue(element, out num); 
       num++; 
       dictionary[element] = num; 
      } 
     } 

     return dictionary; 
    } 

    static private int GetHashCode<E,T>(IEnumerable<T> enumerable) where E : IEnumerable<T> 
    { 
     int hash = 17; 

     foreach (T val in enumerable.OrderBy(x => x)) 
      hash = hash * 23 + val.GetHashCode(); 

     return hash; 
    } 
} 
+0

あなたは本当にここ*一般的な*制約について話していない - あなたのコードは、すでに単一の制約があります。私はあなたが1つの*型引数を使用していることを話していると思う。 Observable を対象とした拡張メソッドに特に満足していますか? (あなたはあなたが与えた呼び出しの拡張メソッドとしても呼んでいないことに注意してください。あなたは2つではなく3つの引数を持っているようです...) –

+0

Jon:あなたは正しいです。私はジェネリック制約をどのように指定するか考えていて、実際には必要ないことを認識しませんでした。 –

答えて

4
static public bool IsEquivalentTo<T>(this IEnumerable<T> first, IEnumerable<T> second) 
2

あなたが最初のものをドロップすると、第二に保つことができます:

static public bool IsEquivalentTo<T>(this IEnumerable<T> first, IEnumerable<T> second) 
1

あなただけIEnumerable<T>ておきEを交換し、ドロップする必要があります例えば文

static public bool IsEquivalentTo<T>(this IEnumerable<T> first, IEnumerable<T> second) 

var firstElementCounts = GetElementCounts<IEnumerable<T>,T>(first, out firstCount); 

static private int GetHashCode<T>(IEnumerable<T> enumerable) 
関連する問題