Методы расширения C # - Как далеко это слишком далеко? - PullRequest
15 голосов
/ 16 декабря 2008

Rails представил некоторые базовые расширения для Ruby, такие как 3.days.from_now, который возвращается, как и следовало ожидать, через три дня в будущем. С помощью методов расширения в C # мы можем теперь сделать нечто подобное:

static class Extensions
{
    public static TimeSpan Days(this int i)
    {
        return new TimeSpan(i, 0, 0, 0, 0);
    }

    public static DateTime FromNow(this TimeSpan ts)
    {
        return DateTime.Now.Add(ts);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(
            3.Days().FromNow()
        );
    }
}

Или как насчет:

static class Extensions
{
    public static IEnumerable<int> To(this int from, int to)
    {
        return Enumerable.Range(from, to - from + 1);
    }
}

class Program
{
    static void Main(string[] args)
    {
        foreach (var i in 10.To(20))
        {
            Console.WriteLine(i);
        }
    }
}

Это в корне неверно, или бывают случаи, когда это хорошая идея, как в фреймворке, подобном Rails?

Ответы [ 7 ]

8 голосов
/ 16 декабря 2008

Мне очень нравятся методы расширения, но я чувствую, что когда они используются вне LINQ, они улучшают читабельность за счет удобства сопровождения.

Взять 3.Days().FromNow() в качестве примера. Это удивительно выразительно, и любой может прочитать этот код и сказать вам, что именно он делает. Это действительно красивая вещь. Как программисты, мы с радостью пишем код с самоописанием и выразительностью, так что он почти не требует комментариев и доставляет удовольствие читать. Этот код имеет первостепенное значение в этом отношении.

Однако, как программисты, мы также несем ответственность за потомство, и те, кто придут за нами, будут тратить большую часть своего времени, пытаясь понять, как работает этот код. Мы должны быть осторожны, чтобы не быть настолько выразительными, что для отладки нашего кода нужно прыгать среди множества методов расширения.

Методы расширения скрывают «как», чтобы лучше выразить «что». Я думаю, это делает их обоюдоострым мечом, который лучше всего использовать (как и все вещи) в умеренных количествах.

6 голосов
/ 16 декабря 2008

Во-первых, мое внутреннее чувство: 3.Minutes.from_now выглядит совершенно круто, но не демонстрирует, почему методы расширения хороши. Это также отражает мой общий взгляд: круто, но я никогда не пропускал их.


Вопрос: 3.Minutes временной интервал или угол?

Пространства имен, на которые ссылается оператор using «обычно», влияют только на типы, теперь они внезапно решают, что означает 3.Minutes.

Так что лучше всего "не дать им сбежать".
Все общедоступные методы расширения в пространстве имен, на которое, вероятно, ссылаются, оказываются «своего рода глобальными» - со всеми потенциальными проблемами, связанными с этим. Сохраните их внутри своей сборки или поместите в отдельное пространство имен, которое добавляется к каждому файлу отдельно.

5 голосов
/ 16 декабря 2008

Лично мне нравится int.To, я неоднозначно отношусь к int.Days, и мне не нравится TimeSpan.FromNow.

Мне не нравится то, что я вижу как причуду для «беглых» интерфейсов, которые позволяют вам писать псевдоанглийский код, но делают это путем реализации методов с именами, которые могут вызывать недоумение в отдельности.

Например, мне это плохо читается:

TimeSpan.FromSeconds(4).FromNow()

Очевидно, это субъективная вещь.

1 голос
/ 16 декабря 2008

Я согласен с СИЗ и постным консерватором в этом вопросе. В Rails есть такая штука, так что это не так уж запутанно. Когда вы пишете свои методы "days" и "fromnow", вы не гарантируете, что ваш код не содержит ошибок. Кроме того, вы добавляете зависимость к своему коду. Если вы поместите ваши методы расширения в их собственный файл, вам понадобится этот файл в каждом проекте. В проекте вы должны включать этот проект, когда вам это нужно.

Все, что сказано, для действительно простых методов расширения (таких как использование Джеффом "left" или использование thatismatt days.fromnow выше), которые существуют в других структурах / мирах, я думаю, это нормально Любой, кто знаком с датами, должен понимать, что означает «3.Days (). FromNow ()».

0 голосов
/ 16 декабря 2008

Моим личным предпочтением было бы пока использовать их экономно и подождать, чтобы увидеть, как их используют Microsoft и другие крупные организации. Если мы начинаем видеть много кода, учебники и книги используют код наподобие 3.Days (). FromNow (), он часто его использует. Если его использует только небольшое количество людей, то вы рискуете из-за того, что ваш код будет слишком сложно поддерживать из-за недостаточного количества людей, знакомых с работой расширений.

В связанной заметке мне интересно, как производительность сравнивается между нормальным циклом for и циклом foreach? Казалось бы, второй метод потребует много дополнительной работы для компьютера, но я недостаточно знаком с концепцией, чтобы знать наверняка.

0 голосов
/ 16 декабря 2008

У каждого языка есть своя перспектива того, каким должен быть язык. Rails и Ruby разработаны с их собственными, очень разными мнениями. PHP имеет совершенно разные мнения, как и C (++ / #) ... как и Visual Basic (хотя, очевидно, нам не нравится их стиль).

Весы имеют много легко читаемых встроенных функций, а не просто контроль над всем. Я бы не хотел, чтобы ОЧЕНЬ много функций приходилось искать каждый раз, когда вы хотите что-то сделать (и это должно быть связано с повышением производительности в раздутой среде), но я лично люблю Rails, потому что это спасает меня много времени развивается.

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

0 голосов
/ 16 декабря 2008

Я нахожусь на консервативной стороне спектра, по крайней мере, в настоящее время, и я против методов расширения. Это просто синтаксический сахар, который для меня не так важен. Я думаю, что это может быть и кошмаром для начинающих разработчиков, если они плохо знакомы с C #. Я бы предпочел инкапсулировать расширения в свои собственные объекты или статические методы.

Если вы собираетесь их использовать, просто, пожалуйста, не злоупотребляйте ими до такой степени, что вы делаете это удобным для себя, но возитесь с кем-то, кто касается вашего кода. : -)

...