我是c#中扩展方法的粉丝,但还没有成功地将扩展方法添加到静态类中,比如Console。
例如,如果我想添加一个名为“WriteBlueLine”的扩展到控制台,这样我就可以:
Console.WriteBlueLine("This text is blue");
我尝试通过添加一个本地的公共静态方法,并将Console作为“this”参数…但是不行!
public static class Helpers {
public static void WriteBlueLine(this Console c, string text)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine(text);
Console.ResetColor();
}
}
这没有添加'WriteBlueLine'方法控制台…我做错了吗?或者要求不可能的事情?
是的,在有限的意义上。
public class DataSet : System.Data.DataSet
{
public static void SpecialMethod() { }
}
这是可行的,但控制台不能,因为它是静态的。
public static class Console
{
public static void WriteLine(String x)
{ System.Console.WriteLine(x); }
public static void WriteBlueLine(String x)
{
System.Console.ForegroundColor = ConsoleColor.Blue;
System.Console.Write(.x);
}
}
这是可行的,因为只要它不在同一个名称空间上。问题是您必须为System的每个方法编写一个代理静态方法。控制台。这并不一定是一件坏事,因为你可以添加这样的内容:
public static void WriteLine(String x)
{ System.Console.WriteLine(x.Replace("Fck","****")); }
or
public static void WriteLine(String x)
{
System.Console.ForegroundColor = ConsoleColor.Blue;
System.Console.WriteLine(x);
}
它的工作方式是你将一些东西钩到标准的WriteLine中。它可以是行数或坏词过滤器或其他什么。只要在命名空间中指定Console,就说WebProject1,然后导入命名空间System, WebProject1。控制台将被选择在系统之上。控制台作为命名空间WebProject1中的这些类的默认值。这段代码将会打开所有的控制台。如果你没有指定System.Console.WriteLine,则WriteLine调用为蓝色。
你能在c#中为类添加静态扩展吗?不,但你可以这样做:
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; }
}
下面是它的工作原理。虽然在技术上不能编写静态扩展方法,但这段代码利用了扩展方法中的漏洞。这个漏洞是你可以在空对象上调用扩展方法而不会得到空异常(除非你通过@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(...)
现在为什么我选择调用默认构造函数作为一个例子,为什么我不只是返回新的T()在第一个代码片段而不做所有的表达式垃圾?
今天是你的幸运日,因为你有一个2。任何高级的。net开发人员都知道,new T()很慢,因为它生成了对System的调用。激活器,它在调用默认构造函数之前使用反射获取默认构造函数。该死的微软!
然而,我的代码直接调用对象的默认构造函数。
静态扩展将比这更好,但紧急时刻需要紧急措施。
不幸的是,你不能扩展静态类
https://onecompiler.com/csharp/3xvbe7axg
using System;
namespace HelloWorld
{
public static class console_extensions {
public static void EXTENSION(this object item) {
System.Console.WriteLine("HELLO THERE!");
}
}
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
Console.EXTENSION();
((Console)null).EXTENSION();
Console l = new Console();
l.EXTENSION();
}
}
}
输出
Compilation failed: 4 error(s), 0 warnings
HelloWorld.cs(16,12): error CS0117: `System.Console' does not contain a definition for `EXTENSION'
/usr/lib/mono/4.5/mscorlib.dll (Location of the symbol related to previous error)
HelloWorld.cs(17,5): error CS0716: Cannot convert to static type `System.Console'
HelloWorld.cs(18,4): error CS0723: `l': cannot declare variables of static types
/usr/lib/mono/4.5/mscorlib.dll (Location of the symbol related to previous error)
HelloWorld.cs(18,16): error CS0712: Cannot create an instance of the static class `System.Console'
/usr/lib/mono/4.5/mscorlib.dll (Location of the symbol related to previous error)
但是你可以将null传递给扩展方法
using System;
namespace HelloWorld
{
public static class static_extensions {
public static void print(this object item, int data = 0) {
Console.WriteLine("EXT: I AM A STATIC EXTENSION!");
Console.WriteLine("EXT: MY ITEM IS: " + item);
Console.WriteLine("EXT: MY DATA IS: " + data);
string i;
if (item == null) {
i = "null";
} else {
i = item.GetType().Name;
}
Console.WriteLine("EXT: MY TYPE IS: " + i + "\n");
}
}
public class Program
{
public static void Main(string[] args)
{
// an extension method can be
// called directly
// (null is an instance)
static_extensions.print(null);
// an extension method can also be
// called directly with arguments
// (null is an instance)
static_extensions.print(null, 1);
// an extension method can also be
// called as part of an instance
int x = 0; // initialize int
x.print();
// an extension method can also be
// called as part of an instance
// and with data
int x2 = 0; // initialize int
x2.print(2);
// an extension method can also be
// called directly from null
// since `null` is an instance
((string)null).print();
// an extension method can also be
// called directly from null
// and with data
// since `null` is an instance
((string)null).print(4);
}
}
}
实例:https://onecompiler.com/csharp/3xvbc8s6w
输出:
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS:
EXT: MY DATA IS: 0
EXT: MY TYPE IS: null
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS:
EXT: MY DATA IS: 1
EXT: MY TYPE IS: null
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS: 0
EXT: MY DATA IS: 0
EXT: MY TYPE IS: Int32
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS: 0
EXT: MY DATA IS: 2
EXT: MY TYPE IS: Int32
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS:
EXT: MY DATA IS: 0
EXT: MY TYPE IS: null
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS:
EXT: MY DATA IS: 4
EXT: MY TYPE IS: null