2011-09-07 13 views
15

Aşağıdaki koda sahibim:Bu kod farklı değerler döndürür. Ancak, istediğim, anonim bir türe karşı güçlü yazılmış bir koleksiyona dönmek.

var foo = (from data in pivotedData.AsEnumerable() 
        select new 
        { 
        Group = data.Field<string>("Group_Number"), 
        Study = data.Field<string>("Study_Name") 
        }).Distinct(); 

Beklendiği gibi bu, ayrı değerleri döndürür. Ancak, istediğim, anonim bir türe karşılık güçlü bir şekilde yazılan bir koleksiyona dönmek, bu yüzden yaptığımda:

var foo = (from data in pivotedData.AsEnumerable() 
        select new BarObject 
        { 
        Group = data.Field<string>("Group_Number"), 
        Study = data.Field<string>("Study_Name") 
        }).Distinct(); 

Bu, farklı değerleri döndürmez, hepsini döndürür. Bunu gerçek nesnelerle yapmanın bir yolu var mı?

+9

'Eşittir()' ve Uygulanışı: – dlev

+0

@dlev GetHashCode'un ne yapması gerekiyor? – BrunoLM

+0

@BrunoLM: Örneğin, bu yanıtı okuyun: http://stackoverflow.com/questions/6305324/why-use-gethashcode-over-equals/6305531#6305531 GetHashCode, Eşittir'in de karşılaştırdığı tüm alanlar üzerinde bir sağlama kodu vermeli ve nesnelerin hızlı arama için karma veya sözlükler için kullanılır. –

cevap

12

için kontrol bu dışarı

var foo = (from data in pivotedData.AsEnumerable() 
       select new BarObject 
       { 
       Group = data.Field<string>("Group_Number"), 
       Study = data.Field<string>("Study_Name") 
       }).GroupBy(x=>x.Group).Select(x=>x.FirstOrDefault()) 

: Önerilen veya kullanım

var foo = (from data in pivotedData.AsEnumerable().Distinct() 
        select new BarObject 
        { 
        Group = data.Field<string>("Group_Number"), 
        Study = data.Field<string>("Study_Name") 
        }); 
+0

Teşekkürler, yaptığım bu. Nesneleri örneğin bir sözlükte saklıyorsam GetHashCode'un daha önemli olduğunu mu söylüyorsunuz? –

+0

@Darren: GetHashCode(), iki nesnenin eşdeğer olup olmadığını görmenin çok hızlı bir yoludur. Bunun nedeni, iki eşdeğer nesnenin her zaman aynı karma kodu içermesidir. İşleme ve dahili olarak kümeleri veya sözlükleri kullanmak için karma kodundan yararlanan birçok LINQ yöntemi vardır. Böylece, LINQ kullanırken, her ikisi de önemlidir. –

+1

@Darren: Sadece decompiled Distinct() ve gerçekten hashing kullanan bir Set kullanın. –

3

DistinctBarObject nesnelerin karşılaştırılamıyor. Bu nedenle, aynı içeriklere sahip olsalar bile, birbirlerinden tamamen farklı olan referanslarını karşılaştırır.

Yani ya sen Equals yöntemi üzerine veya Distinct için özel bir EqualityComparer kaynağı. Equals'u uygularken GetHashCode'un üzerine yazmayı unutmayın, aksi takdirde nesnelerin örneğin bir sözlüğe veya anahtar olarak (örneğin, HashSet<BarObject>) içine koyarsanız garip sonuçlar üretir. Distinct'in dahili olarak hashset kullanması (tam olarak bilmiyorum) olabilir.

HereGetHashCode için iyi uygulamaların bir koleksiyonudur. için Distinct() (ve diğer birçok LINQ özellikler) için daha fazla bilgi http://blog.jordanterrell.com/post/LINQ-Distinct()-does-not-work-as-expected.aspx

1

bu deneyin iş, karşılaştırılan sınıf (örneğinizdeki BarObject), Equals() ve GetHashCode() uygulamalarını uygulamalıdır veya alternatif olarak Distinct()'a argüman olarak ayrı bir IEqualityComparer<T> sağlar.

Birçok LINQ yöntemi, performans için GetHashCode()'dan faydalanır; çünkü dahili olarak O (1) aramalar için karma kullanımı olan benzersiz öğeleri tutmak için Set<T> gibi şeyler kullanırlar. Ayrıca,iki nesnesinin eşdeğeri olup olmadığını ve hangisinin kesinlikle olmadığını - GetHashCode() elbette düzgün olarak uygulandığı sürece hızlıca söyleyebilir.

Yani tamlığı için Equals() ve GetHashCode() uygulamak LINQ karşılaştırmak veya ayrı IEqualityComparer<T> uygulaması oluşturmak niyetinde bütün derslerini yapmalıdır.türünüze `GetHashCode()`

var foo = (from data in pivotedData.AsEnumerable() 
       select new 
       { 
       Group = data.Field<string>("Group_Number"), 
       Study = data.Field<string>("Study_Name") 
       }).Distinct().Select(x => new BarObject { 
       Group = x.Group, 
       Study = x.Study 
       }); 
+0

Bu ** olabilir ** olabilir, ancak aynı semantik değildir. Eğer 'Grup' ve 'Çalışma' dışında başka alanlar varsa, bazı kopyalar solabilir. –

+0

Evet, başka alanlar var. Bunları kısırlaştırmak için attım. Bu yaklaşımı başlangıçta denedim. Yine de teşekkürler. –

4

Ya dlev olarak yapın:

+0

Thats (benim düşüncemde) çok güzel bir çözüm değildir, çünkü Distinct çok daha hızlıdır ve op istediğini yapmak için tasarlanmıştır. Ancak blog yazısı ilginçti. Görünüşe göre “Distinct” ın dahili olarak “HashSet” kullandığını varsayıyordum. –

İlgili konular