C# Feature Idea: Static Extension Methods
Extension methods are really useful - no two ways about it. Being able to add my own methods to an existing class makes for some very readable code.
Extension methods, however, are currently only instance methods. There's no syntax for defining a static extension method on a type rather than an instance. For example, suppose I wanted to define a static method called Yesterday() on the DateTime class, so I could do this:
var d = DateTime.Yesterday();
It's a trivial example, I know, but you get the idea. Another example might be to create a static method to create an instance of a type - like the TryParse() method we get on a few inbuilt classes.
I'm thinking that the syntax could use generics and look something like this:
public static DateTime Yesterday<this DateTime>()
{
return DateTime.Today.AddDays(-1);
}
So I've used the "this" keyword (in much the same way that normal extension methods do) except I've used it in the generic type argument. DateTime now has a static method called Yesterday.
Obviously static extension methods would only call static members (unless they take a parameter).
Perhaps C# 4.0 could introduce a feature like this. Would you use it?

# Trackback from Jason Haley on 7/02/2008 3:26 AM
# Trackback from Reflective Perspective - Chris Alcock » The Morning Brew #27 on 7/02/2008 6:03 PM
Comments
# Sasha Goldshtein
7/02/2008 7:01 AM
I don't feel a strong connection between this kind of feature and generics, so I find it difficult to second your syntax.
By the way, what's so wrong with just doing:
static class DateTimeEx {
public static DateTime Yesterday() { ... }
}
It looks almost as good as the original, and if you have a good coding convention in place it might even work.
Alternatively, you could go for:
namespace Extensions {
static class DateTime {
public static System.DateTime Yesterday() {...}
}
}
And then you'd have:
DateTime yesterday = Extensions.DateTime.Yesterday();
Not so bad either.
# mabster
7/02/2008 8:51 AM
Yeah, the link to generics is tenuous at best, but it's a language construct we already have to tie a method to a type (rather than passing in a parameter of type Type), so it seemed like a logical way of declaring an extension method on a type rather than an instance.
Certainly both of your examples work, but then old-fashioned static methods also work in place of extension methods, but I think we all agree that the latter makes for more readable code.
I think if I was reading code that said:
var d = DateTime.Yesterday;
... then I'd instantly recognize that "d" is a DateTime. If I saw this:
var d = DateTimeEx.Yesterday;
... then it's a little less clear.
# Skup
7/02/2008 7:24 PM
Hi,
the use of generics on a method is usualy not used to tell on which object the method is, but to give a type to arguments... so i'm not sure it's the better option.
I was thinking to enable static class inheritance...
public static class DateTimeEx : DateTime
{
...
}
since the class is static it cannot extend the instance, but propose new static methods for it..
the caveats is that we would like to use the DateTime, and it is not natural to have methods declared on a derived type appearing on a base type...
Should continue to think about it..
# david alpert
8/02/2008 7:42 PM
I would definitely use the feature; i just wrote some custom Constraints for NUnit 2.4.6 and wanted to add some static properties to the Has SyntaxHelper so that i could write:
Assert.That(p, Has.MyCustomConstraint);
This is very readable syntax; the static properties on the Has class return instances of Constraint classes that Assert.Test then applies to p - very cool and DSL-like.
I agree, however, that the use of Generics syntax muddies the issue a bit.
How about simply adding the static keyword into the extension method declaration? And while we're at it, enhancing the extension method syntax to support extension properties like so:
public static class HasExtensions {
public static MyCustomConstraint MyCustomConstraint(static this Has) {
get {return new MyCustomConstraint(); }
}
}
# Brett
13/02/2008 4:19 PM
How about
public static DateTime Yesterday(this DateTime) { }
or
public static DateTime Yesterday(static DateTime d) { }
(similar to above but no need for this keyword)
# mabster
14/02/2008 2:40 PM
Actually, the second one sounds good. The 'static' keyword in place of the 'this' keyword. It wouldn't actually need the "d" though, since there is no "d" to act on:
public static DateTime Yesterday(static DateTime) { }
# David Nelson
20/02/2008 7:29 AM
The difference between instance extension methods and the static extension methods you propose is that instance extension methods reorder the code resulting in making it more readable, whereas your static extension methods merely replace one type with another, without making the code more readable. I think all you are doing here is adding language complexity without adding value.
# mabster
20/02/2008 7:39 AM
Hi David,
I'm not sure I'm "replacing one type with another" at all. My DateTime.Yesterday() example doesn't introduce any new types - it just adds a static method to DateTime.
David Alpert's example of an Assert.That() overload above is another good one.
# david alpert
20/02/2008 7:41 AM
back to my NUnit example, static extension methods would allow me to add my custom properties to an _existing_ static helper class.
this improves readability, no?
Wouldn't you rather see
DateTime y = DateTime.Yesterday
than
DateTime y = DateTimeEx.Yesterday
or
DateTime y = Extensions.DateTime.Yesterday()
Isn't the first one more clear, more readable, and, provided that the static extension code is in a findable location, more maintainable?
# David Nelson
22/02/2008 9:55 AM
Matt and David Alpert,
My point was that all you gain from this is the ability to go from David's second example to his first, i.e. "replacing" DateTimeEx with DateTime. That seems to me to be an extraordinarily small gain in exchange for additional language complexity and reduced maintainability.
# mabster
22/02/2008 10:48 AM
Yeah, I won't deny that it's a small gain.
The readability benefit is clear though. Imagine something like this:
Assert.That(x == y).And.That(a != b).AndEx.IsEmpty(myString);
Because I had to define my own "IsEmpty" static method, I had to create an "AndEx" class to contain it. That harms readability IMHO.
It's a trivial thing but it'd be cool to have.
# David Nelson
26/02/2008 1:11 AM
I agree there is a small readability gain. I just don't think it meets the "minus 100 points" test. This is of course a subjective assessment. But in my opinion, extension methods as they exist today are already like handing a loaded gun to a toddler; I fear what they will do the future maintainability of the language. I am not normally one to worry about what how a powerful feature might be abused, but in this case I am afraid that the lure of "readability" will cause many, many people to go too far with this feature. I am also concerned about the enormous potential for breaking changes (several people from the various .NET teams have blogged about this, including Eric Lippert). Instance extension methods introduce a new variation of the fragile base class problem, and static extension methods would just compound the problem.
# Vitaly Orlov
4/03/2008 6:54 AM
I think mabster asked for something I have been wishing from the birth of C#.
You might think it's a small gain but I think it's not. Because most stuff is dangerous if you abuse them. I mean look at var feature of C# 3.0. If it's abused, it would be the most fearful nightmare for C# IMO.
So stuff like this really helps with the workflow, and clarity, and just like instance extension methods are extremely easy to understand. Just show the syntax, and done! You already learnt it.
Is there a way we can pass this onto C# team? I already heard they are planning to add instance extension properties.
# Andrew Tobin
4/03/2008 10:31 AM
I always find it a tad bizarre when someone mentions that a function in C# would be a nightmare if abused.
Anything in a programming language is a nightmare if it's abused.
Heck, commenting is a nightmare if it's abused (for the next person maintaining).
I don't think, when speaking about programming languages, that the fact it _could_ be abused is a valid reasoning for not having a piece of functionality.
User applications, certainly, but we need to place some trust in the developers hands that they'll do the best they can to be effective, efficient, and work to best practices.
On the downside, you get viruses, worms, keyloggers, etc, etc.
On the plus side, for those of us who do the right thing, we get a bit more power that makes us efficient and allows us to write better software.
It's okay if you want to write something managed that saves me from having to worry about the background stuff (memory management, etc), but there's no need to protect me from misusing something, because I'll learn a better way as soon as I can.
# David Nelson
5/03/2008 2:16 AM
@Andrew,
As I said, "I am not normally one to worry about what how a powerful feature might be abused." The reason I don't usually worry about it is because the potential gain far outweighs the risk of some developers abusing the feature. However, in this case, I believe that the potential gain is so small that it does not outweigh that risk, or the other negative impacts that adding a feature to a language has.
# Vitaly Orlov
5/03/2008 7:34 AM
But isn't it the same thing with instance extension methods?
# David Nelson
5/03/2008 8:21 AM
@Vitaly,
No, its not the same. Instance extension methods physically rearrange the code to be more in line with what we expect to see when looking at object-oriented code. This results in a substantial increase in readability. But static extension methods do not rearrange the code; they merely replace one type name with another type name within an expression. So the readability gain is extremely small, and as I said, not worth it IMHO.
# Vitaly Orlov
6/03/2008 4:02 AM
But instance extension methods don't cover all bases in what we want to see.
For instance, IMO it's more readable to use:
Vector3.Dot(v1, v2)
than
v1.Dot(v2)
I think it's these kind of things that static extension methods would shine.
# David
7/03/2008 1:22 AM
@Vitaly,
You can accomplish that same thing with:
Vector3Math.Dot(v1, v2)
Maybe its not quite as readable, but its close. This is what I meant when I said that static extension methods only result in a very small readability gain, which is not (IMHO) worth implementing a language feature for.
# Vitaly Orlov
7/03/2008 5:25 AM
I see what you mean. But we could do this if we didn't have instance extension methods, right?
Scramble(myString)
instead of
myString.Scramble()
Aren't these the same too? Or is it because instance extension methods avoid referencing arguments, like:
Scramble(ref myString)
# David Nelson
7/03/2008 6:44 AM
Yes, technically instance extension methods do not allow us to do anything we couldn't do before (unless you are relying on duck typing like LINQ is, in which case they are necessary). But the point is that they rearrange the code to increase readability by turning functional statements like Scramble(myString) into object-oriented statements like myString.Scramble(). Static extension methods don't rearrange the code; ALL they do is replace one type name (Vector3Math) with another type name (Vector3) within an otherwise identical expression.
# Vitaly Orlov
7/03/2008 10:40 AM
That makes sense. When you said they are necessary for duck typing, did you mean using var?
If so, I thought they were separate things. Can you please give me an example?
# David Nelson
8/03/2008 3:20 AM
No, I don't mean the use of var. Implicitly typed variables are not a form of duck typing, they are just a way to refer to anonymous types.
I have written a post about LINQ and duck typing on my blog at commongenius.com/.../linq-and-duck-typing.aspx.
# Vitaly Orlov
8/03/2008 6:18 AM
Thanks. I got it now.
# Jeff
4/12/2008 7:43 AM
I can think of one problem with using conventions proposed in examples like the following in that it doesn't lend itself to good practices with regard to reflection, refactoring, and other types of static analysis.
Vector3Math.Dot(v1, v2)
DateTime y = DateTimeEx.Yesterday
DateTime y = Extensions.DateTime.Yesterday()
The reason is that by using DateTimeEx by convention bares no actual code connectino between DateTimeEx and DateTime.
A little off topic, but an interesting aspect of static extension methods would be that this would may provide for a way of extending Factory methods to provide more customized construction logic. Sort of the same thing that makes the new type initialization syntax so handy { P1 = "1", P2 = 2}.
# Szymon Matyjaszek
7/01/2009 3:40 AM
I totally agree about static extension methods.
In web applications an ordinary practice is to separate data logic and web-related logic (stuff that relies on HttpContext in any way). Since C#3.0 there's a comfy way to do this without defining hundreds of new classes. Assuming it's a data-related application and you have your entity logic in SomeProject.SomeNamespace, you just put some extension methods in SomeProject.SomeNamespace.Web (preferably in some other assembly file) and that's it. You do to your classes exactly the same thing as System.Linq does to IEnumerable for example. Still, due to the lack of static extension methods, whenever you need a static web-aware method for your base logic class, you have to put together a "Helper" or "Manager" class which gets it done. Then instead of doing SomeEntity.FromSession(...) for example, you do SomeEntityManager.GetSomeEntityFromSession(...) which is far from perfectly comfortable. Aside from that, in the end mostly you realize that you already have 50 of those helpers/managers, each defining just a couple of methods. In such scenarios, static extension methods would be a cure.
As for the syntax, I like this one:
public static DateTime Yesterday(static DateTime) { }
Leave a Comment