IEnumerable <T> 'den ICollection <T>' ye dönüştürülemiyor


91

Aşağıdakileri tanımladım:

public ICollection<Item> Items { get; set; }

Bu kodu çalıştırdığımda:

Items = _item.Get("001");

Aşağıdaki mesajı alıyorum:

Error   3   
Cannot implicitly convert type 
'System.Collections.Generic.IEnumerable<Storage.Models.Item>' to 
'System.Collections.Generic.ICollection<Storage.Models.Item>'. 
An explicit conversion exists (are you missing a cast?)

Birisi neyi yanlış yaptığımı açıklayabilir mi? Numaralandırılabilir, Koleksiyonlar ve ToList () kullanımı arasındaki fark konusunda kafam çok karışık.

Eklenen bilgiler

Daha sonra kodumda aşağıdakilere sahibim:

for (var index = 0; index < Items.Count(); index++) 

Öğeleri bir IEnumerable olarak tanımlayabilir miyim?


3
_İtem türü ve Get (string) imzası (özellikle dönüş türü) hakkında daha fazla bilgi verebilir misiniz?
Dr Andrew Burnett-Thompson

Türü neden böyle değiştirmiyorsunuz? public IEnumerable<Item> Items { get; set; }Buna sahip olmak için özel bir sebebiniz var ICollectionmı?
Gölge Sihirbazı Sizin İçin Kulak

IEnumerable <T> Get (string pk);
Samantha JT Star

Yanıtlar:


113

ICollection<T>IEnumerable<T>sonucunu atamak için bundan devralır

IEnumerable<T> Get(string pk)

Bir üzere ICollection<T>iki yol vardır.

// 1. You know that the referenced object implements `ICollection<T>`,
//    so you can use a cast
ICollection<T> c = (ICollection<T>)Get("pk");

// 2. The returned object can be any `IEnumerable<T>`, so you need to 
//    enumerate it and put it into something implementing `ICollection<T>`. 
//    The easiest is to use `ToList()`:
ICollection<T> c = Get("pk").ToList();

İkinci seçenekler daha esnektir, ancak çok daha büyük bir performans etkisine sahiptir. Diğer bir seçenek, arabirim IEnumerable<T>tarafından eklenen ekstra işlevselliğe ihtiyaç duymadığınız sürece sonucu bir olarak saklamaktır ICollection<T>.

Ek Performans Yorumu

Sahip olduğunuz döngü

for (var index = 0; index < Items.Count(); index++)

bir üzerinde çalışır IEnumerable<T>ama verimsizdir; her çağrı , tüm öğelerin eksiksiz bir numaralandırılmasını Count()gerektirir . Bir koleksiyonu ve özelliği (parantez olmadan) kullanın veya bir foreach döngüsüne dönüştürün:Count

foreach(var item in Items)

1
ICollection tarafından eklenen ek işlevler nelerdir?
Samantha JT Star

7
ICollection<T>manipüle edilebilir (ayrıntılar için belgeye bakın), ancak bir IEnumerable<T>yalnızca numaralandırılabilir.
Anders Abel

Farklı LINQ sorguları çalıştırabileceğim bir şeye ihtiyacım var. Listeye böyle bir şey eklememe veya yapmama gerek yok. Bu, ICollection ile daha iyi durumda olacağım anlamına mı geliyor?
Samantha JT Star

LINQ çalışmaktadır, IEnumerable<T>bu IEnumerable<T>durumda yeterlidir.
Anders Abel

31

'Dan' IEnumerable<T>ye doğrudan dönüştüremezsiniz ICollection<T>. Bunu dönüştürmek için ToListyöntemini kullanabilirsiniz IEnumerable<T>.ICollection<T>

someICollection = SomeIEnumerable.ToList();


Bu benim için çalışıyor. Ama dönüştürmek benim için iyi bir fikir mi yoksa IEnumerable'ı Öğeler için tür olarak kullanmak daha mı iyi? IEnumerable kullanırsam, programımda daha sonra gerekirse Öğeler üzerinde daha fazla işlem yapabilmek için bunu yapıyor muyum?
Samantha JT Star

ICollection zaten IEnumerable'ı uyguluyor. Mevcut eylemler konusunda endişeleriniz varsa, ICollection'a gitmeniz gerektiğini düşünüyorum. İkisi arasındaki gerçek farkı okuyup daha sonra neyi kullanmak istediğinize karar vermeniz daha iyi olur
Haris Hasan

ToList () kullansaydım ne gibi avantajlara sahip olacağımı anlamaya çalışıyorum. Verilere sahip olduktan sonra, LINQ sorgularını Öğelere karşı çalıştırmak istiyorum.
Samantha JT Star

ToList () çalışacaktır, ancak yorumlarınızda belirttiğiniz gibi Get () bir ICollection döndürür, bu yüzden gerçekten sadece ICollection <T> için bir atama yapmanız veya daha da iyisi Get to ICollection <T> dönüş imzasını değiştirmeniz gerekir. . ToList veya ToArray kullanmak işe yarayacak, ancak aynı zamanda gereksiz bir bellek oluşturma / kopyalama işlemine neden olacak
Dr. Andrew Burnett-Thompson

LINQ sorgularını hem IEnumerable hem de ICollection için çalıştırabilirsiniz. Avantajları .. Şu anda bildiğim bir tanesi, Count ICollection'ın sayımını koruduğu ve IEnumerable'ın kaç öğeye sahip olduğunu hesaplayarak sonuç verdiği. ICollection, Ienumerables'ın sunmadığı ek kaldırma yöntemi sağlar
Haris Hasan

1

Soruyla ilgili daha fazla bilgi bekleniyor:

lütfen öğenin türü ve Get'in imzası hakkında daha fazla bilgi verin

Deneyebileceğiniz iki şey:

  • _İtem'in dönüş değerini dönüştürmek için.Get to (ICollection)
  • ikinci olarak _item.Get ("001") kullanmak için. ToArray () veya _item.Get ("001"). ToList ()

Lütfen ikinci dizinin dizi kopyası için bir performans vuruşuna neden olacağını unutmayın. Get'in imzası (dönüş türü) bir ICollection değilse, o zaman ilki çalışmaz, IEnumerable değilse ikincisi çalışmaz.


Sorularınıza ve yorumlarınıza açıklık getirdikten sonra, ICollection'a dönen _item.Get ("001") türünü şahsen beyan ederim. Bu, gereksiz bir oluşturma / kopyalama işlemini içerecek herhangi bir dönüştürme veya dönüştürme (ToList / ToArray aracılığıyla) yapmanız gerekmeyeceği anlamına gelir.

// Leave this the same
public ICollection<Item> Items { get; set; }

// Change function signature here:
// As you mention Item uses the same underlying type, just return an ICollection<T>
public ICollection<Item> Get(string value); 

// Ideally here you want to call .Count on the collectoin, not .Count() on 
// IEnumerable, as this will result in a new Enumerator being created 
// per loop iteration
for (var index = 0; index < Items.Count(); index++) 

Saygılarımla,


1
İmza: IEnumerable <T> Get (string pk); Öğeler, iade edilen Öğe kayıtlarını tutmak için kullanılır. Daha sonra bir rapor oluşturmak için bunları yineliyorum. İşe yarayan herhangi bir şeyi kullanabilirim. En iyi veri türünün ne olacağını düşünüyorsunuz?
Samantha JT Star

1
Get eşleşmesi için Öğelerin veri türünü IEnumerable <T> olarak değiştirmenizi veya Öğelerle eşleşecek şekilde Get to ICollection <T> dönüş türünü değiştirmenizi öneririm. Bu ikisinin aynı temel tür olduğunu varsayıyorum, sadece farklı şekilde bildirilmiş? Gereksiz bellek ayırma ve dizi kopyası gerçekleştiren ToList () veya ToArray () kullanmaktan kaçınmak istediğiniz türdeyse. Aynı tip değillerse, biraz dönüşüm yapmanız gerekir
Dr. Andrew Burnett-Thompson

Öğeleri daha sonra nerede kullandığımı göstermek için soruya ekledim. Aynı temel türü söylerken haklısınız.
Samantha JT Star

Tamam, o zaman herhangi bir dönüştürme (ToList / ToArray yoluyla, yavaş olan) veya çevrim yapmanıza gerek kalmayacağı için Get'in dönüş türünü değiştirirdim. Umarım bu yardımcı olur :)
Dr.Andrew Burnett-Thompson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.