Làm cách nào để đảm bảo rằng FirstOrDefault <KeyValuePair> đã trả về một giá trị


91

Đây là một phiên bản đơn giản của những gì tôi đang cố gắng thực hiện:

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));

Vì 'xyz' không có trong từ điển, phương thức FirstOrDefault sẽ không trả về giá trị hợp lệ. Tôi muốn có thể kiểm tra tình huống này nhưng tôi nhận ra rằng tôi không thể so sánh kết quả với "null" vì KeyValuePair là một chuỗi. Mã sau không hợp lệ:

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

Khi bạn cố gắng biên dịch mã, Visual Studio gặp lỗi sau:

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

Làm cách nào để kiểm tra xem FirstOrDefault đã trả về giá trị hợp lệ chưa?


1
Bạn có một lỗi ở đó, nhưng tôi cho rằng đó là thứ sao chép-dán: ngày không phải là danh sách và bạn không thể sử dụng thêm trên KeyValuePair.
Kobi

ooops ... bạn nói đúng, tôi đang nhập từ bộ nhớ và rõ ràng là tôi đã mắc lỗi. Cảm ơn đã chỉ ra điều đó.
desautelsj

1
Nó có thể là: var days = new Dictionary <int, string> ();
Even Mien

Câu trả lời:


156

FirstOrDefaultkhông trả về null, nó trả về default(T).
Bạn nên kiểm tra:

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

Từ MSDN -Enumerable.FirstOrDefault<TSource> :

mặc định( TSource ) nếu nguồn trống; nếu không, phần tử đầu tiên trong nguồn .

Ghi chú:


17
+1, KeyValuePair là kiểu giá trị (struct), không phải kiểu tham chiếu (lớp) hoặc kiểu giá trị nullable, vì vậy nó không thể là null.
Lucas

6
@ paper1337 - Cảm ơn, nhưng tôi còn thiếu ở typeofđâu? Mã này biên dịch và hoạt động.
Kobi

3
Tôi đến đây vì nó không rõ ràng với tôi, điều gì default(KeyValuePair<T1, T2>)sẽ dẫn đến. Ok, lẽ ra nó phải khá rõ ràng, rằng nó sẽ dẫn đến một KVP trống. Nhưng khi "là rõ ràng" không phải là một cách tiếp cận tốt để viết các ứng dụng thích hợp (và thực hiện hiện tại của tôi là quá phức tạp để rõ ràng / sạch kích trường hợp này), tôi đã thử nó với một dự án mới và - thực sự - nó quay trở lại một KeyValuePairvới tính chất KeyValuecon người cả hai NULL.... chỉ để an toàn cho một số người khác trong 5 phút ngu ngốc này ;-)
Nicolas

@Nicolas - Không có ngu ngốc ở đây. Bạn nên tự mình kiểm tra và đảm bảo rằng bạn hiểu mã của mình. Tôi đã thêm một liên kết vào defaulttừ khóa, rõ ràng là nó bị thiếu ở đây. Cảm ơn!
Kobi

1
@JeffBridgman - Đó thực sự là một điểm tốt! Cụ thể ở đây là không thể, vì chúng tôi đang làm việc với KeyValuePair. Nếu bạn đã có mã chung, day.Equalsthậm chí không null-an toàn, và tôi đã sử dụngEqualityComparer<T>.Default.Equals(day, defaultDay)
Kobi

54

Đây là cách rõ ràng và ngắn gọn nhất theo ý kiến ​​của tôi:

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

Điều này hoàn toàn xoay quanh việc sử dụng những thứ có giá trị mặc định kỳ lạ cho cấu trúc.


13
Vấn đề ở đây, là có tiềm năng (tùy thuộc vào thực hiện) mà những ngày đếm được sẽ được liệt kê hai lần, hoặc thậm chí tệ hơn, trở về giá trị khác nhau giữa Any () và First () gọi
Ray Booysen

@RayBooysen Một lệnh gọi ToArray hoặc ToList sẽ giải quyết được vấn đề và bạn có thể sử dụng Count / Length và Indexer.
Bảng điều khiển

1
Lưu ý rằng câu trả lời của @ Ray không áp dụng ở đây, vì dayslà a Dictionary<int,string>. Vì vậy, nó sẽ được coi là một IEnumerable<KeyValuePair<int,string>>, sau đó hoạt động như mong đợi khi Any()First()được gọi. Tôi đoán rằng có những triển khai khác có thể hoạt động khác nhau như IEnumerable<>. Tôi không biết liệu tôi có đang thiếu một cái gì đó không.
Emanuele Bellini

0

Bạn có thể làm điều này thay thế:

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));

và sau đó :

if (day.Key == null) {
    System.Diagnotics.Debug.Write("Couldn't find day of week");
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.