Вставить тест для нуля в одном выражении LINQ - PullRequest
4 голосов
/ 12 октября 2011

Давайте начнем с простого примера класса:

public class Foo
{
    public DateTime Date { get; set; }
    public decimal Price { get; set; }
}

Затем создайте список:

List<Foo> foos = new List<Foo>;

Я хотел бы вернуть отформатированную цену или «N / A» одного элемента в списке на основе даты, поэтому, например, я мог бы написать:

Foo foo = foos.FirstOrDefault(f => f.Date == DateTime.Today);
string s = (foo != null) ? foo.Price.ToString("0.00") : "N/A";

Я хотел бы объединить вышеупомянутые 2 строки наподобие следующего:

string s = foos.FirstOrDefault(f => f.Date == DateTime.Today).Price.ToString("0.00") ?? "N/A";

Однако, это не дает того, чего я хочу, потому что, если (f => f.Date == DateTime.Today) не возвращает Foo, тогда выдается NullReferenceException.

Следовательно, возможно ли с помощью LINQ создать всего 1 оператор для возврата отформатированной цены или «N / A»?

Ответы [ 3 ]

10 голосов
/ 12 октября 2011

Если сначала отфильтровать, а затем выбрать, вы можете использовать оператор объединения нулей (??), например:

string price = foos.Where(f => f.Date == DateTime.Today)
                   .Select(f => f.Price.ToString())
                   .FirstOrDefault() ?? "N/A";
5 голосов
/ 12 октября 2011

Один из способов - просто проверить, равен ли нуль FirstOrDefault перед вызовом ToString:

var todayFoo = foos.FirstOrDefault(f => f.Date == DateTime.Today);
var s = todayFoo != null ? todayFoo.Price.ToString("0.00") : "N/A";

Другим способом было бы создать метод расширения для объединяющего оператора, который также принимает делегат проекции, что-то вроде:

public static class ObjectExt
{
    public static T2 Coalesce<T1, T2>(
         this T1 obj, Func<T1, T2> projection, T2 defaultValue)
    {
        if (obj == null)
            return defaultValue;

        return projection(obj);
    }
}

А затем назовите это так:

var s = foos
         .FirstOrDefault(f => f.Date == DateTime.Today)
         .Coalesce(t => t.Price.ToString("0.00"), "N/A");
2 голосов
/ 12 октября 2011

string s = foos.Where(f => f.Date == DateTime.Today).Select(f => f.Price.ToString("0.00")).FirstOrDefault();

...