2011-11-04 10 views
6

グループタイプを強く型付けしたいが、私が正しくグループ化しないという問題がある。なぜ匿名型を使用し、GroupByにはない明示的な型を使用していますか?

1 
3 
Press any key to continue . . . 

私は結果がすなわちかかわらず、明示的な型を使用して、同じでもないことを期待するだけの3項目で一つのグループでなければなりません:以下のコード...

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace ConsoleApplication35 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Foo> foos = new List<Foo>(); 
      foos.Add(new Foo() { Key = "Test" }); 
      foos.Add(new Foo() { Key = "Test" }); 
      foos.Add(new Foo() { Key = "Test" }); 

      var groups = foos.GroupBy<Foo, dynamic>(entry => new 
      { 
       GroupKey = entry.Key 
      }); 

      Console.WriteLine(groups.Count()); 

      groups = foos.GroupBy<Foo, dynamic>(entry => new GroupingKey() 
      { 
       GroupKey = entry.Key 
      }); 

      Console.WriteLine(groups.Count()); 

     } 

     public class Foo 
     { 
      public string Key { get; set; } 
     } 

     public class GroupingKey 
     { 
      public string GroupKey { get; set; } 
     } 
    } 
} 

出力を参照してください。 1項目の3つのグループではありません。ここで何が起こっているのですか?

更新 私がされたIEqualityComparerを追加し、それが動作するようになりました!以下を参照してください:

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace ConsoleApplication35 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Foo> foos = new List<Foo>(); 
      foos.Add(new Foo() { Key = "Test" }); 
      foos.Add(new Foo() { Key = "Test" }); 
      foos.Add(new Foo() { Key = "Test" }); 

      var groups = foos.GroupBy<Foo, dynamic>(entry => new //GroupingKey() 
      { 
       GroupKey = entry.Key 
      }); 

      Console.WriteLine(groups.Count()); 

      groups = foos.GroupBy<Foo, GroupingKey>(entry => new GroupingKey() 
      { 
       GroupKey = entry.Key 
      }, new GroupingKeyEqualityComparer()); 

      Console.WriteLine(groups.Count()); 

     } 

     public class Foo 
     { 
      public string Key { get; set; } 
     } 

     public class GroupingKey 
     { 
      public string GroupKey { get; set; }    
     } 

     public class GroupingKeyEqualityComparer : IEqualityComparer<GroupingKey> 
     { 
      #region IEqualityComparer<GroupingKey> Members 

      public bool Equals(GroupingKey x, GroupingKey y) 
      { 
       return x.GroupKey == y.GroupKey; 
      } 

      public int GetHashCode(GroupingKey obj) 
      { 
       return obj.GroupKey.GetHashCode(); 
      } 

      #endregion 
     } 
    } 
} 

出力:

1 
1 
Press any key to continue . . . 

これはかなりのJaredParによって与えられた答えを確認!

+0

2つ目の 'groups'を別の変数名に変更し、' を使う代わりに ''を使用しますか?このインスタンスでは、切断が一般的な型指定である可能性があります。 –

+0

@Joel - 実際に動的なことは、IEqualityComparerを追加して型を変更するように強制するまで、違いは見られませんでした。 – Jim

答えて

7

最初のバージョンでは、GroupKeyという1つのプロパティを持つ匿名タイプを作成しています。 C#の匿名型は構造的な等価性を使用するため、値の等価性はキーの等価性になります。これにより、それらは適切にグループ化されます。

2番目のケースでは、GroupingKeyという名前のカスタムタイプを使用しています。これは、デフォルトまたは参照平等を使用しているようです。したがって、インスタンスはどれも等しいとみなされないため、異なるグループに入れられます。

関連する問題