C# Extension Methods - How far is too far?

2020-05-19 07:01发布

Rails introduced some core extensions to Ruby like 3.days.from_now which returns, as you'd expect a date three days in the future. With extension methods in C# we can now do something similar:

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()
        );
    }
}

Or how about:

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);
        }
    }
}

Is this fundamentally wrong, or are there times when it is a good idea, like in a framework like Rails?

7条回答
虎瘦雄心在
2楼-- · 2020-05-19 07:36

I agree with siz and lean conservative on this issue. Rails has that sort of stuff baked in, so it's not really that confusing ever. When you write your "days" and "fromnow" methods, there is no guarantee that your code is bug free. Also, you are adding a dependency to your code. If you put your extension methods in their own file, you need that file in every project. In a project, you need to include that project whenever you need it.

All that said, for really simple extension methods (like Jeff's usage of "left" or thatismatt's usage of days.fromnow above) that exist in other frameworks/worlds, I think it's ok. Anyone who is familiar with dates should understand what "3.Days().FromNow()" means.

查看更多
不美不萌又怎样
3楼-- · 2020-05-19 07:41

I like extension methods a lot but I do feel that when they are used outside of LINQ that they improve readability at the expense of maintainability.

Take 3.Days().FromNow() as an example. This is wonderfully expressive and anyone could read this code and tell you exactly what it does. That is a truly beautiful thing. As coders it is our joy to write code that is self-describing and expressive so that it requires almost no comments and is a pleasure to read. This code is paramount in that respect.

However, as coders we are also responsible to posterity, and those who come after us will spend most of their time trying to comprehend how this code works. We must be careful not to be so expressive that debugging our code requires leaping around amongst a myriad of extension methods.

Extension methods veil the "how" to better express the "what". I guess that makes them a double edged sword that is best used (like all things) in moderation.

查看更多
做自己的国王
4楼-- · 2020-05-19 07:44

First, my gut feeling: 3.Minutes.from_now looks totally cool, but does not demonstrate why extension methods are good. This also reflects my general view: cool, but I've never really missed them.


Question: Is 3.Minutes a timespan, or an angle?

Namespaces referenced through a using statement "normally" only affect types, now they suddenly decide what 3.Minutes means.

So the best is to "not let them escape".
All public extension methods in a likely-to-be-referenced namespace end up being "kind of global" - with all the potential problems associated with that. Keep them internal to your assembly, or put them into a separate namespace that is added to each file separately.

查看更多
一纸荒年 Trace。
5楼-- · 2020-05-19 07:47

My personal preference would be to use them sparingly for now and to wait to see how Microsoft and other big organizations use them. If we start seeing a lot of code, tutorials, and books use code like 3.Days().FromNow() it makes use it a lot. If only a small number of people use it, then you run the risk of having your code be overly difficult to maintain because not enough people are familiar with how extensions work.

On a related note, I wonder how the performance compares between a normal for loop and the foreach one? It would seem like the second method would involve a lot of extra work for the computer, but I'm not familiar enough with the concept to know for sure.

查看更多
▲ chillily
6楼-- · 2020-05-19 07:49

I'm on the conservative side of the spectrum, at least for the time being, and am against extension methods. It is just syntactic sugar that, to me, is not that important. I think it can also be a nightmare for junior developers if they are new to C#. I'd rather encapsulate the extensions in my own objects or static methods.

If you are going to use them, just please don't overuse them to a point that you are making it convenient for yourself but messing with anyone else who touches your code. :-)

查看更多
何必那么认真
7楼-- · 2020-05-19 07:50

Personally I like int.To, I am ambivalent about int.Days, and I dislike TimeSpan.FromNow.

I dislike what I see as a bit of a fad for 'fluent' interfaces that let you write pseudo English code but do it by implementing methods with names that can be baffling in isolation.

For example, this doesnt read well to me:

TimeSpan.FromSeconds(4).FromNow()

Clearly, it's a subjective thing.

查看更多
登录 后发表回答