Why can a .NET delegate not be declared static?
当我试图编译以下内容时:
1 | public static delegate void MoveDelegate (Actor sender, MoveDirection args); |
我收到一个错误消息:"修改器'static'对此项无效。"
我将在一个单独的类(调用委托)中实现这一点。问题是,当我使用另一个类中的singleton实例调用委托(从标识符,而不是类型)时,无论出于什么原因,我都不能这样做,即使我声明委托是非静态的。显然,我只能在委托是静态的情况下通过类型直接引用它。
这背后的原因是什么?我正在使用MonoDevelop2.4.2。
更新
使用以下代码尝试其中一个建议后:
1 2 3 4 5 6 7 8 9 10 | public void Move(MoveDirection moveDir) { ProcessMove(moveDir); } public void ProcessMove(MoveDirection moveDir) { Teleporter.MoveMethod mm = new Teleporter.MoveMethod(Move); moveDelegate(this, moveDir); } |
我收到一个处理错误,它指出movemethod必须是一个类型,而不是标识符。
试试这个:
1 2 | public delegate void MoveDelegate(object o); public static MoveDelegate MoveMethod; |
所以方法变量可以定义为静态的。关键字
如何分配静态方法字段的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public class A { public delegate void MoveDelegate(object o); public static MoveDelegate MoveMethod; } public class B { public static void MoveIt(object o) { // Do something } } public class C { public void Assign() { A.MoveMethod = B.MoveIt; } public void DoSomething() { if (A.MoveMethod!=null) A.MoveMethod(new object()); } } |
您正在声明一个
1 2 3 4 5 6 7 8 9 | public delegate void BoringDelegate(); internal class Bar { public static BoringDelegate NoOp; static Bar() { NoOp = () => { }; } } |
委托声明基本上声明了一个方法签名,它只包含有关其参数和返回类型的信息。由于同一个委托可以同时指向静态方法和实例方法,因此将方法签名本身设置为静态或实例是没有意义的。
一旦你宣布你的代表为:
1 | public delegate void MoveDelegate (Actor sender, MoveDirection args); |
这意味着任何此类委托都必须指向接受一个
因此,在某处声明
1 | private MoveDelegate _myMoveDelegate; |
请记住,该方法应具有匹配的签名:
1 2 3 4 5 6 7 8 9 10 | // parameters and return type must match! public void Move(Actor actor, MoveDirection moveDir) { ProcessMove (moveDir); } public static void MoveStatic(Actor actor, MoveDirection moveDir) { ProcessMove (moveDir); } |
然后,可以将此方法分配给其他位置的委托:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | private void SomeOtherMethod() { // get a reference to the Move method _myMoveDelegate = Move; // or, alternatively the longer version: // _myMoveDelegate = new MoveDelegate(Move); // works for static methods too _myMoveDelegate = MoveStatic; // and then simply call the Move method indirectly _myMoveDelegate(someActor, someDirection); } |
知道.NET(从v3.5版开始)提供了一些预定义的通用委托(
1 2 3 | // you can simply use the Action delegate to declare the // method which accepts these same parameters private Action<Actor, MoveDirection> _myMoveDelegate; |
使用这些委托更易读,因为您可以通过查看委托本身立即识别参数的签名(而在您的情况下,需要查找声明)。
委托声明实际上是一个类型声明。它不能是静态的,就像不能定义静态枚举或结构一样。
但是,我宁愿使用接口而不是原始委托。
考虑一下:
4在您的呼叫代码中:
1 2 3 4 5 |
这在精神上类似于策略设计模式,并允许您将
最后,您可以使用控制框架的反转来自动在您的
定义委托,在静态类中为其声明一个实例变量。
1 2 3 4 5 6 | public delegate void MoveDelegate (Actor sender, MoveDirection args); public static MyClass { public static MoveDelegate MoveDelegateInstance; } |
1 | public static delegate void MoveDelegate (Actor sender, MoveDirection args); |
我来告诉你当你宣布代表时发生了什么
编译器创建一个名为
因为不能按静态类型扩展任何非静态类型。
所以这就是编译器不允许静态委托声明的原因。但仍然可以有静态委托引用。