2017-01-02 22 views
7

Powiedzmy, że mam klasę pracowników, a GetAllEmployees() zwraca listę instancji pracownika. Chcę pracowników Grupy przez Departament i płci, więc odpowiedź mam togrupa przy użyciu anonimowego typu w Linq

var employeeGroup = Employee.GetAllEmployees() 
          .GroupBy(x => new { x.Department, x.Gender }) // I don't understand this anonymous type 
          .OrderBy(g => g.Key.Department) 
          .ThenBy(g => g.Key.Gender) 
          .Select(g => new { //I can understand this anonymous type 
           Dept = g.Key.Department, 
           Gender = g.Key.Gender, 
           Employees = g.OrderBy(x => x.Name) 
          }); 

Mam dwa pytania:

  1. Dlaczego typ anonimowy pozwala grupę wielu kluczy przez?

  2. Nie rozumiem pierwszy typ anonimowy, ponieważ z mojego zrozumienia, format typ anonimowy powinien być tak

    nowy {pole1 = x.Department, pole2 = x.Gender}

Jak to możliwe, że pierwszy anonimowy typ może zawierać pola? To znaczy, że to poprawna składnia, aby napisać coś takiego:

var anonymous = new {field1 = 1,field2 =2} 

Ale nie będzie skompilować błąd, jeśli napiszę to tak:

var anonymous = new {1, 2} //compile error !!! 
+0

'field1' i' field2' są pola. Kiedy 'wybierasz' robisz projekcję w typ anonimowy, gdy' groupBy' dostajesz coś innego: 'IEnumerable >' – Crowcoder

+0

Jeśli pominiesz część 'field =', pole fieldname jest pobierane ze zmiennej/właściwości. Zobacz ["typy anonimowe"] (http://stackoverflow.com/documentation/c%23/765/anonymous-types/2612/creating-an-anonymous-type#t=201701021356107409379) – Nico

Odpowiedz

15

anonimowych typy mogą być użyte tutaj do grupy według wielu pól , ponieważ GroupBy używa domyślnego porównywania równości.
Domyślny porównywanie równości dla typów anonimowych używa domyślnego porównywania równości dla każdej właściwości typu anonimowego.

Tak więc dla pierwszego anonimowego typu dwie instancje są równe, jeśli oba Department s i oba Gender s są równe (zgodnie z ich domyślnymi porównywarkami równości).

Można wyobrazić typ anonimowy jest coś takiego:

public class AnonymousType1 
{ 
    public int Department { get; set; } // I don't know your department type 
    public int Gender { get; set; } // neither your gender type 

    public int GetHashCode() { return Department.GetHashCode()^Gender.GetHashCode(); } 
    public bool Equals(AnonymousType1 other) 
    { 
     if (ReferenceEquals(other, null)) return false; 
     return Department == other.Department && Gender == other.Gender; 
    } 
} 

Drugie pytanie jest łatwe, zbyt: kompilator używa nazwy właściwości (Department z x.Department i Gender z x.Gender) jako nazwy dla właściwości anonimowego typu.

Więc

var anon = new { employee.Department, employee.Gender } 

tworzy typ z właściwością zwanego Department i właściwość o nazwie Gender.
Oczywiście to może pracować tylko z istniejących Properties/nazwy, a nie z wartościami stałymi jak

var anon = new {1,2}; // fails to compile, no names provided. 
+0

Dziękuję za odpowiedź. Tak jasne – grooveline