Bir öğe seçmek için Linq kodu


105

Eşleşen bir öğeyi seçmek için buna benzer çok kod yazarken buluyorum

var item = (from x in Items where x.Id == 123 select x).First();

Bunu yapmanın daha temiz bir yolu var mı yoksa bu benim anlayacağım kadar kısa mı?

DÜZENLEME: "Linq sözdizimi kullanarak daha temiz bir yol" demeliydi. Lambda sözdiziminin zaten farkındaydım ve bu aslında tek yol gibi görünmeye başladı. Yine de bazı yararlı bilgiler aldım, bu yüzden cevaplayan herkese teşekkürler.


5
Kişisel olarak kaçınırım Single()ve SingleOrDefault()EĞER verilerin zaten benzersiz olduğunu bilirsem (örneğin, bu kısıtlamaya sahip bir veritabanından vb.), Çünkü Single()olası bir kopyayı bulmak için listenin geri kalanını taramaya zorlar, ama bu benim. Bu noktada benzersizliğinizi güçlendirmeniz gerekiyorsa, Single()aileyi, yoksa First()aileyi kullanın .
James Michael Hare 1811

Yanıtlar:


176

Linq sorgu sözdizimini ne kadar beğendiğinize bağlı olarak, uzantı yöntemlerini doğrudan şu şekilde kullanabilirsiniz:

var item = Items.First(i => i.Id == 123);

Ve liste boşsa bir hata atmak istemiyorsanız FirstOrDefault, öğe türü için varsayılan değeri döndüren kullanın ( nullbaşvuru türleri için):

var item = Items.FirstOrDefault(i => i.Id == 123);

if (item != null)
{
    // found it
}

Single()ve SingleOrDefault()ayrıca kullanılabilir, ancak bir veritabanından veya zaten benzersizliği garanti eden bir şeyden okuyorsanız, herhangi bir yineleme ve atma olup olmadığını görmek için listeyi taraması gerektiğinden rahatsız olmazdım. First()ve FirstOrDefault()ilk maçta dur, böylece daha verimli olurlar.

Of First()ve Single()onlar atmak nerede ailesi, burada:

  • First() - boşsa / bulunmazsa atar, yinelenirse atmaz
  • FirstOrDefault() - boşsa / bulunmazsa varsayılan döndürür, yinelenirse atmaz
  • Single() - boşsa / bulunmazsa atar, kopya varsa atar
  • SingleOrDefault() - boşsa / bulunmazsa varsayılan döndürür, yinelenen varsa atar

1
Sanırım orada iki eşittir işareti eksik. Olmalıi.Id == 123
davehale23

18

FirstOrDefault veya SingleOrDefault , senaryonuza ve sıfır veya birden fazla eşleşme olup olmadığını işlemek isteyip istemediğinize bağlı olarak yararlı olabilir:

FirstOrDefault: Bir dizinin ilk öğesini veya öğe bulunamazsa varsayılan bir değeri döndürür.

SingleOrDefault: Bir dizinin tek öğesini veya dizi boşsa varsayılan bir değeri döndürür; dizide birden fazla öğe varsa bu yöntem bir istisna atar

Bunun linq 'from' sorgusunda nasıl çalıştığını bilmiyorum ama lambda sözdiziminde şöyle görünüyor:

var item1 = Items.FirstOrDefault(x => x.Id == 123);
var item2 = Items.SingleOrDefault(x => x.Id == 123);

DB zamanı açısından hangisi en verimli? Bir varchar'ım olsaydı, tam bir eşleşme istedim ama mümkün olabilir mi?
Piotr Kula

2
Kabul edilen cevap, bunu tam olarak ele alır, ancak esasen FirstOrDefault bir eşleşme bulur bulmaz durur, ancak SingleOrDefault tam olarak bir eşleşme olduğundan emin olmak için tüm listeyi incelemelidir .
stuartd

12

Tercih edilen yöntemler şunlardır:

var item = Items.SingleOrDefault(x => x.Id == 123);

Veya

var item = Items.Single(x => x.Id == 123);

Teşekkürler - yani bu durumda linq gösterimi yok ve lambda kullanmam gerekiyor mu?
Mikey Hogarth 1811

Bu oldukça iyi. Linq'i pek kullanmadım, bu yüzden bu yöntemlerin farkında olduğumdan bile emin değilim.
wageoghe

1
Tek yöntem, dönüş değerinin benzersiz olup olmadığını kontrol eder. Yani koleksiyonunuz büyükse, çok zaman alabilir. İlk yöntem, yüklemle eşleşen ilk öğeyi döndürür.
meziantou

@wageoghe James'in cevabı linq kullanmıyor - Single ve SingleOrDefault yöntemleri IEnumerable uygulamasının bir parçası.
Mikey Hogarth 1811

12

Sadece birinin hayatını kolaylaştırmak için, lambda ifadeli linq sorgusu

(from x in Items where x.Id == 123 select x).FirstOrDefault();

içinde a olan bir SQL sorgusu ile sonuçlanır select top (1).


9

Bu, buna kısaltılsa iyi olur.

var item = Items.First(x => x.Id == 123);

Sorgunuz şu anda numaralandırılabilir içindeki tüm sonuçları topluyor (ve birden fazla olabilir) ve ardından bu kümeden ilkini alarak gereğinden fazla iş yapıyor.

Single / SingleOrDefault değerlidir, ancak yalnızca tüm koleksiyon boyunca yinelemek ve bu eşleşmeyi seçmenin yanı sıra eşleşmenin benzersiz olduğunu doğrulamak istiyorsanız. First / FirstOrDefault, gerçekte kaç tane yinelenen var olduğuna bakılmaksızın, yalnızca ilk eşleşmeyi alır ve ayrılır.


4

Uzantı yöntemi sözdizimini kullanabilirsiniz:

var item = Items.Select(x => x.Id == 123).FirstOrDefault();

Bunun dışında, kendi özel "First" ve "FirstOrDefault" genişletme yöntemlerinizi yazmadan ne kadar özlü olabileceğinizden emin değilim.


Bunun amaçlanan davranış olduğunu sanmıyorum. Bu Select talimatı döndürür (aslında döndürmez, ancak return için seçer), her Item öğesi için bir bool koleksiyonu, öğe olarak döndürülenlerin ilki, basitçe bool olur. Chris Hannon'ın çözümünü kullanın
Leonardo Daga

Belki daha önce belirtilmiş Whereolanın tersini kastediyorsunuz Select, ancak bu cevap yanlış. C # 'de seç, sonuçları IEnumerable <bool> olarak değiştirir, böylece boolilk öğe için bir alıyorsunuzx.Id == 123
bradlis7

2

Benim için neyin işe yaradığını size söyleyeceğim:

int id = int.Parse(insertItem.OwnerTableView.DataKeyValues[insertItem.ItemIndex]["id_usuario"].ToString());

var query = user.First(x => x.id_usuario == id);
tbUsername.Text = query.username;
tbEmail.Text = query.email;
tbPassword.Text = query.password;

Kimliğim, sorgulamak istediğim satırdır, bu durumda onu bir radGrid'den aldım, sonra onu sorgulamak için kullandım, ancak bu sorgu bir satır döndürür, sonra sorgudan aldığınız değerleri metin kutusuna veya herhangi bir şeye atayabilirsiniz , Bunları metin kutusuna atamam gerekiyordu.

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.