Ярлык для "ноль, если объект нуль, или object.member, если объект не нуль"

Я пытаюсь написать общий метод расширения, который позволяет мне сделать это:

this.startDate = startDateXAttribute.NullOrPropertyOf<DateTime>(() =>
{
    return DateTime.Parse(startDateXAttribute.Value);
});

NullOrPropertyOf() вернется null если он используется на null объект (например, если startDateXAttribute было null) или вернуть результат Func если это не ноль.

Как бы выглядел этот метод расширения?

3 ответа

Решение

Там нет краткой формы для этого; его реализация - довольно часто запрашиваемая функция. Синтаксис может быть что-то вроде:

x = foo.?bar.?baz;

То есть, x равно нулю, если foo или foo.bar равны нулю, и результат foo.bar.baz, если ни один из них не равен нулю.

Мы рассматривали это для C# 4, но это не сделало это где-нибудь в верхней части списка приоритетов. Мы будем иметь это в виду для гипотетических будущих версий языка.

ОБНОВЛЕНИЕ: C# 6 будет иметь эту функцию. См. http://roslyn.codeplex.com/discussions/540883 для обсуждения конструктивных соображений.

Класс XAttribute предоставляет явный оператор преобразования для этого:

XAttribute startDateXAttribute = // ...

DateTime? result = (DateTime?)startDateXAttribute;

Для общего случая, лучший вариант, вероятно, такой:

DateTime? result = (obj != null) ? (DateTime?)obj.DateTimeValue : null;

Это то, что вы ищете? Я думаю, что он сломается, если вы передадите необнуляемый тип значения, но он должен работать, когда вы используете обнуляемые типы. Пожалуйста, дайте мне знать, если я что-то упустил.

public static class Extension
{
    public static T NullOrPropertyOf<T>(this XAttribute attribute, Func<string, T> converter)
    {
        if (attribute == null)
        {
            return default(T);
        }
        return converter.Invoke(attribute.Value);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Func<string, DateTime?> convertDT = (string str) =>
        {
            DateTime datetime;
            if (DateTime.TryParse(str, out datetime))
            {
                return datetime;
            }
            return null;
        };
        Func<string, string> convertStr = (string str) =>
        {
            return str;
        };
        XAttribute x = null;
        Console.WriteLine(x.NullOrPropertyOf<string>(convertStr));
        Console.WriteLine(x.NullOrPropertyOf<DateTime?>(convertDT));
        XName t = "testing";
        x = new XAttribute(t, "test");
        Console.WriteLine(x.NullOrPropertyOf<string>(convertStr));
        x = new XAttribute(t, DateTime.Now);
        Console.WriteLine(x.NullOrPropertyOf<DateTime?>(convertDT));
    }
}
Другие вопросы по тегам