FirstOrDefault <KeyValuePair> öğesinin bir değer döndürdüğünden nasıl emin olabilirim


92

İşte yapmaya çalıştığım şeyin basitleştirilmiş bir versiyonu:

var days = new Dictionary<int, string>();
days.Add(1, "Monday");
days.Add(2, "Tuesday");
...
days.Add(7, "Sunday");

var sampleText = "My favorite day of the week is 'xyz'";
var day = days.FirstOrDefault(x => sampleText.Contains(x.Value));

Sözlükte 'xyz' olmadığından, FirstOrDefault yöntemi geçerli bir değer döndürmeyecektir. Bu durumu kontrol edebilmek istiyorum ama sonucu "null" ile karşılaştıramayacağımı fark ettim çünkü KeyValuePair bir yapıdır. Aşağıdaki kod geçersiz:

if (day == null) {
    System.Diagnotics.Debug.Write("Couldn't find day of week");
}

Kodu derlemeye çalıştığınızda, Visual Studio aşağıdaki hatayı atar: We you try compile the code, Visual Studio throws the following error:

Operator '==' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair<int,string>' and '<null>'

FirstOrDefault'un geçerli bir değer döndürdüğünü nasıl kontrol edebilirim?


1
Orada bir hatanız var, ancak bunun bir kopyala-yapıştır meselesi olduğunu varsayıyorum: günler bir liste değil ve KeyValuePair'de add'yi kullanamazsınız.
Kobi

ooops ... haklısınız, bellekten yazıyordum ve belli ki bir hata yaptım. Gösterdiğiniz için teşekkürler.
desautelsj

1
Muhtemelen şöyleydi: var days = new Dictionary <int, string> ();
Mien

Yanıtlar:


156

FirstOrDefaultnull döndürmez, döndürür default(T).
Şunları kontrol etmelisiniz:

var defaultDay = default(KeyValuePair<int, string>);
bool b = day.Equals(defaultDay);

Gönderen MSDN -Enumerable.FirstOrDefault<TSource> :

kaynak boşsa varsayılan ( TSource ); aksi takdirde, kaynaktaki ilk öğe .

Notlar:


17
+1, KeyValuePair bir referans türü (sınıf) veya boş değer atanabilir bir değer türü değil, bir değer türüdür (struct), bu nedenle boş olamaz.
Lucas

6
@ paper1337 - Teşekkürler, ama nereyi kaçırıyorum typeof? Bu kod derler ve çalışır.
Kobi

3
Buraya geldim çünkü benim için net değildi, neyin default(KeyValuePair<T1, T2>)sonuçlanacağı. Tamam, boş bir KVP ile sonuçlanacağı oldukça açık olmalıydı. Ancak "açık olmak", uygun uygulamaları yazmak için iyi bir yaklaşım olmadığından (ve mevcut uygulamam bu vakayı açık / net bir şekilde kışkırtmak için çok karmaşık), yeni bir projeyle denedim ve - aslında - KeyValuePairözellikleri Keyve Valuevarlığı ile ikisi de NULL.... bu 5 dakikalık aptallığı başkalarını güvence altına almak için ;-)
Nicolas

@Nicolas - Burada aptallık yok. Kendinizi kontrol etmek ve kodunuzu anladığınızdan emin olmak her zaman iyi bir fikirdir. defaultAnahtar kelimeye bir bağlantı ekledim , burada açıkça eksik. Teşekkürler!
Kobi

1
@JeffBridgman - Bu gerçekten iyi bir nokta! Özellikle burada bu mümkün değil çünkü birlikte çalışıyoruz KeyValuePair. Eğer jenerik kodunuz olsaydı, day.Equalsboş güvenli bile değil ve kullanmış olurdumEqualityComparer<T>.Default.Equals(day, defaultDay)
Kobi

56

Bence bu en açık ve özlü yol:

var matchedDays = days.Where(x => sampleText.Contains(x.Value));
if (!matchedDays.Any())
{
    // Nothing matched
}
else
{
    // Get the first match
    var day = matchedDays.First();
}

Bu, yapılar için tuhaf varsayılan değer öğeleri kullanarak tamamen ortadan kalkar.


13
Bununla ilgili sorun, numaralandırılabilir günlerin iki kez numaralandırılması veya daha da kötüsü Any () ve First () çağrıları arasında farklı değerler döndürme potansiyeli (uygulamaya bağlı olarak) olmasıdır
Ray Booysen

@RayBooysen ToArray veya ToList çağrısı sorunu çözer ve Count / Length ve bir Indexer kullanabilirsiniz.
Konsol

1
@ Ray'in cevabının burada geçerli olmadığını unutmayın, çünkü daysa Dictionary<int,string>. Bu yüzden bir olarak kabul edilecek ve çağrıldığında IEnumerable<KeyValuePair<int,string>>beklendiği gibi davranacak . Sanırım farklı davranabilen başka uygulamalar da var . Bir şeyi kaçırdığımı bilmiyorum. Any()First()IEnumerable<>
Emanuele Bellini

0

Bunun yerine bunu yapabilirsiniz:

var days = new Dictionary<int?, string>();   // replace int by int?
days.Add(1, "Monday");
days.Add(2, "Tuesday");
...
days.Add(7, "Sunday");

var sampleText = "My favorite day of the week is 'xyz'";
var day = days.FirstOrDefault(x => sampleText.Contains(x.Value));

ve sonra :

if (day.Key == null) {
    System.Diagnotics.Debug.Write("Couldn't find day of week");
}
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.