在回家的路上,我有了一个想法:创建Func / Action扩展,这将允许c#中的一些很好的语法糖。
理论示例...为Func / Action的各种排列创建一个扩展,允许您为方法的执行计时。
当我到家并尝试一个例子时,我发现这不可能。我认为这是c#的缺点/不一致。代表和方法是相同的(在理论上)。
public static class Extensions
{
public static void Time(this Action action)
{
// Logic to time the action
action();
}
}
public class Example
{
public void Main()
{
Action action = RunApp;
Action actionLambda = () => { };
Action actionDelegate = delegate () { };
Extensions.Time(RunApp); // Works
Extensions.Time(() => { }); // Works
Extensions.Time(delegate() { }); // Works
Extensions.Time(action); // Works
Extensions.Time(actionLambda); // Works
Extensions.Time(actionDelegate); // Works
action.Time(); // Works
actionLambda.Time(); // Works
actionDelegate.Time(); // Works
((Action) RunApp).Time(); // Works
((Action) delegate () { }).Time(); // Works
((Action) (() => { })).Time(); // Works
// These should all be the same!
RunApp.Time(); // No good: "Example.RunApp() is a method which is not valid in the given context"
() => { }.Time(); // No good: Operator '.' cannot be applied to operand of type 'lambda expression'"
(() => { }).Time(); // No good: Operator '.' cannot be applied to operand of type 'lambda expression'"
delegate() { }.Time(); // No good: "Operator '.' cannot be applied operand of the type 'anonymous method'"
}
public void RunApp()
{
// Stuff...
}
}
我理解Func / Action是c#与代理和方法组相比的新增内容,但为什么它们都不能同样行事呢?
答案 0 :(得分:0)
Action很好地以简单的方式封装了委托,而无需显式声明您的委托。在C#中,delegate是将方法捕获为类型的语言机制。你需要一个类型来创建一个扩展方法....所以,简化回代表...
public static class Extensions
{
public delegate void Del();
public static void Time(this Del action)
{
// Logic to time the action
action();
}
}
class Program
{
static void Main(string[] args)
{
((Extensions.Del)(() => { })).Time();
}
}
语言不会自动将方法转换为Del,您需要明确这样做。方法本身不是类型,委托是捕获它们的机制。从根本上说,在c#中,委托与方法不同。这是C#的解决方案,有方法的类型安全指针。
要记住的另一件事是你能做到: -
public static class Extensions
{
public delegate void Del();
public delegate void Del2();
public static void Time(this Del action)
{
// Logic to time the action
action();
}
public static void Time(this Del2 action)
{
// Logic to time the action
action();
}
public static void Time(this Action action)
{
// Logic to time the action
action();
}
}
class Program
{
static void Main(string[] args)
{
((Extensions.Del)(() => { })).Time();
((Extensions.Del2)(() => { })).Time();
((Action)(() => { })).Time();
(() => { })).Time(); // no way to know what type this should be coerced to
}
}
现在您的方法可以被捕获为多种不同的类型。