Can I add extension methods to an existing static class?
I'm a fan of extension methods in C#, but haven't had any success adding an extension method to a static class, such as Console.
For example, if I want to add an extension to Console, called 'WriteBlueLine', so that I can go:
Console.WriteBlueLine("This text is blue");
I tried this by adding a local, public static method, with Console as a 'this' parameter... but no dice!
public static class Helpers {
public static void WriteBlueLine(this Console c, string text)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine(text);
Console.ResetColor();
}
}
This didn't add a 'WriteBlueLine' method to Console... am I doing it wrong? Or asking for the impossible?
No. Extension methods require an instance variable (value) for an object. You can however, write a static wrapper around the ConfigurationManager
interface. If you implement the wrapper, you don't need an extension method since you can just add the method directly.
public static class ConfigurationManagerWrapper
{
public static ConfigurationSection GetSection( string name )
{
return ConfigurationManager.GetSection( name );
}
.....
public static ConfigurationSection GetWidgetSection()
{
return GetSection( "widgets" );
}
}
Can you add static extensions to classes in C#? No but you can do this:
public static class Extensions
{
public static T Create<T>(this T @this)
where T : class, new()
{
return Utility<T>.Create();
}
}
public static class Utility<T>
where T : class, new()
{
static Utility()
{
Create = Expression.Lambda<Func<T>>(Expression.New(typeof(T).GetConstructor(Type.EmptyTypes))).Compile();
}
public static Func<T> Create { get; private set; }
}
Here's how it works. While you can't technically write static extension methods, instead this code exploits a loophole in extension methods. That loophole being that you can call extension methods on null objects without getting the null exception (unless you access anything via @this).
So here's how you would use this:
var ds1 = (null as DataSet).Create(); // as oppose to DataSet.Create()
// or
DataSet ds2 = null;
ds2 = ds2.Create();
// using some of the techniques above you could have this:
(null as Console).WriteBlueLine(...); // as oppose to Console.WriteBlueLine(...)
Now WHY did I pick calling the default constructor as an example, and AND why don't I just return new T() in the first code snippet without doing all of that Expression garbage? Well todays your lucky day because you get a 2fer. As any advanced .NET developer knows, new T() is slow because it generates a call to System.Activator which uses reflection to get the default constructor before calling it. Damn you Microsoft! However my code calls the default constructor of the object directly.
Static extensions would be better than this but desperate times call for desperate measures.
Its not possible.
And yes I think MS made a mistake here.
Their decision does not make sense and forces programmers to write (as described above) a pointless wrapper class.
Here is a good example: Trying to extend static MS Unit testing class Assert: I want 1 more Assert method AreEqual(x1,x2)
.
The only way to do this is to point to different classes or write a wrapper around 100s of different Assert methods. Why!?
If the decision was been made to allow extensions of instances I see no logical reason to not allow static extensions. The arguments about sectioning libraries does not stand up once instances can be extended.
链接地址: http://www.djcxy.com/p/17444.html上一篇: C#有扩展属性吗?
下一篇: 我可以将扩展方法添加到现有的静态类吗?