Подтвердить что ты не робот

Методы расширения С# - насколько далеко?

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

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?

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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


Вопрос: есть ли 3.Minutes промежуток времени или угол?

Пространства имен, на которые ссылается с помощью инструкции "нормально", влияют только на типы, теперь они вдруг принимают решение о том, что означает 3.Minutes.

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

Ответ 3

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

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

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

TimeSpan.FromSeconds(4).FromNow()

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

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

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

Ответ 7

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

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