Многочисленные расширения с гарантией отсутствия бросков - PullRequest
4 голосов
/ 04 декабря 2011

Лично я являюсь поклонником свободного синтаксиса интерфейса методов расширения IEnumerable / List в C # как клиента.То есть я предпочитаю синтаксис, подобный этому:

    public void AddTheseGuysToSomeLocal(IEnumerable<int> values)
    {
        values.ToList().ForEach(v => _someLocal += v);
    }

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

Давайте предположим, что я не хочу рассматривать нулевое перечисление как исключительное - я хочу, чтобы это приводило к тому, что я оставляю некоторые локальные как есть - я бы добавил нулевую охрану.Но на мой вкус это немного синтаксически шумно, и этот шум накапливается в тех случаях, когда вы объединяете их вместе в гибкий интерфейс, и промежуточные результаты также могут быть нулевыми.

Итак, я создалкласс с именем SafeEnumerableExtensions, который предлагает гарантию отсутствия бросков, рассматривая пустые перечислимые значения (списки) как пустые.Примеры методов включают в себя:

    //null.ToList() returns empty list
    public static List<T> SafeToList<T>(this IEnumerable<T> source)
    {
        return (source ?? new List<T>()).ToList();
    }

    //x.SafeForEach(y) is a no-op for null x or null y
    //This is a shortcut that should probably go in a class called SafeListExtensions later
    public static void SafeForEach<T>(this List<T> source, Action<T> action)
    {
        var myAction = action ?? new Action<T>(t => { });
        var mySource = source ?? new List<T>();
        mySource.ForEach(myAction);
    }

    public static void SafeForEach<T>(this IEnumerable<T> source, Action<T> action)
    {
        SafeToList(source).SafeForEach(action);            
    }

Теперь мой оригинальный метод красивее, чем если бы был нулевой сторож, но так же безопасен, так как нулевой результат в no-op:

    public void AddTheseGuysToSomeLocal(IEnumerable<int> values)
    {
        values.ForEach(v => _someLocal += v);
    }

Итак, мой вопрос двоякий.(1) Я предполагаю, что я не настолько оригинален, чтобы быть первым человеком, который когда-либо думал об этом - кто-нибудь знает, существует ли существующая библиотека, которая делает это или что-то подобное?И (2) кто-нибудь использовал указанную библиотеку или реализовал подобную схему и испытывал неприятные последствия, или же кто-нибудь может предвидеть неприятные последствия для таких действий?Это даже хорошая идея?

(я нашел этот вопрос при проверке дубликатов, но я не хочу явно делать эту проверку в клиентах - я хочу, чтобы класс расширенияделать это неявно и не мешать клиентам этим дополнительным вызовом метода)

1 Ответ

7 голосов
/ 04 декабря 2011

И (2) кто-нибудь использовал указанную библиотеку или реализовал схему, подобную этой и испытал неприятные последствия, иначе кто-нибудь может предвидеть неприятные последствия для чего-то подобного? Это даже хорошая идея?

Лично я бы посчитал это плохой идеей. В большинстве случаев передача null нумерации или нуля Func, вероятно, не предназначена.

Вы «исправляете» проблему, которая может привести к, по-видимому, связанным с этим проблемам позже в будущем. Вместо этого я бы предпочел выдать исключение в этом случае, чтобы вы нашли эту проблему в своем коде на раннем этапе ( "Fail fast" ).

...