为什么MyDeler"静态",因为我可以通过类名访问MyDeler,但我不能说明公共"静态"委托void MyDeler(),也不能通过MyClass实例访问d,就像在新的MyClass.d()中一样?
此外,为什么我必须新建MyClass才能使用MyVoidAction?
见下面的代码:
using System;
public class MyClass
{
public delegate void MyDeler();
public Action MyVoidAction;
}
class MainClass
{
static void Main()
{
MyClass.MyDeler d = () => Console.WriteLine("my deler");
d();
// MyClass.MyVoidAction mva1 = () => Console.WriteLine("my void action"); // not allowed, why?
MyClass meClass = new MyClass();
meClass.MyVoidAction = () => Console.WriteLine("my void action");
meClass.MyVoidAction();
}
}
我查了一下这个答案:Accessibility between Action and Delegate
这清理了很多,但我不确定我是100%的。所以根据那个答案,委托void MyDeler()定义了一个类型,这让我感到困惑,因为我想象的是:
using System;
class MainClass
{
class MyClass
{
public static class DelegateClass
{
public void DoDel() // isn't even legal?
{
Console.WriteLine("DoDel()");
}
}
}
static void Main()
{
//MyClass.DelegateClass d = new asdf // ??? something like this?
}
}
帮助表示赞赏!
答案 0 :(得分:0)
MyDeler
是类型声明,而不是变量声明。您无法将内容存储在其中或分配给它。
要创建用于存储MyDeler
实例的字段,请将此行添加到MyClass
:
public MyDeler MyDelerField;
现在你可以分配给它了。
答案 1 :(得分:0)
为什么MyDeler是“静态的”,因为我可以通过类名访问MyDeler,但我无法明确说公共“静态”委托void MyDeler(),也不能通过MyClass的实例访问d,如在新的MyClass.d()?
MyDeler
的声明在MyClass
中声明类型。它类似于声明任何其他嵌套类型,如:
class MyClass
{
public class MyNestedClass { }
}
它是类型 MyClass
的成员,不是MyClass
的任何实际实例,也不是MyClass
类{{1}成员将是。
嵌套类型既不是“实例”也不是“静态”,因为它是类型系统的一部分,而不是类本身的一部分。
为什么我必须新建一个MyClass才能使用MyVoidAction?
因为static
是该类的成员,并且是实例成员。因此,您需要拥有该类的实例才能访问它。
委托void MyDeler()定义了一个类型,这让我感到困惑,因为我想象这样的事情
你在MyVoidAction
的例子中的声明正在做一些完全不同的事情。 C#的一个不幸的方面是使用public static class DelegateClass
来引用各种不同的东西。它不像Java那么糟糕,但它仍然可能令人困惑(正如你所发现的那样)。
在该声明中,使用单词static
使不使static
成为包含类型DelegateClass
的“静态成员”。相反,MyClass
声明作为static
声明的一部分,意味着整个班级仅包含class
个成员。
因此,当您在没有static
关键字的情况下声明DoDel()
时,您试图在您承诺仅声明静态成员的类中声明实例成员,即该方法。如果将static
添加到方法声明中,它将进行编译。
不这样做会使该示例中的static
类与其他示例中的DelegateClass
成员类似。它仍然是类型声明,在MyVoidAction
类中声明嵌套类型,并且仍然遵循类型规则,而不是类成员。但我希望至少可以向你解释为什么令你困惑的例子就像它一样。
答案 2 :(得分:0)
让我们揭开神秘面纱:
当您声明MyDeler
:
public delegate void MyDeler();
您正在做的是定义一种执行方式"委托"。换句话说,你说有一个跟随这个签名的方法,我打算继续引用它。为了让编译器识别这些引用,将使用此类型。
接下来你需要实际拥有一个指向该方法的真实指针,因为这只是你的定义"。这就是为什么你需要一个类型变量" MyDeler"您可以为其分配要调用的实际方法:
MyClass.MyDeler d = () => Console.WriteLine("my deler");
这一行说"创建一个名为d
的类型为MyClass.MyDeler
的变量,该变量包含对此内联方法的引用"。从这里开始,当你调用d();
时,指针实际上会执行内联方法。
对于行动:
public Action MyVoidAction;
您现在宣布该类的公开属性。因此,在使用此属性之前,您需要该类的实例。
这里的技巧是Action是委托的已知定义。 Microsoft有一个内置类型,您可以使用它而不是声明自己的void MyDeler();
。它本质上是语法糖但记住,它仍然是一个类型,并且你已经创建了一个公共属性,你现在需要为它分配实际执行的方法,正如我们之前讨论的那样,你需要一个实例:
MyClass meClass = new MyClass(); //Instance creation
meClass.MyVoidAction = () => Console.WriteLine("my void action"); //Tell your delegate what to delegate to.
meClass.MyVoidAction(); //Run the inline method!
我希望有所帮助。
答案 3 :(得分:0)
Action
和delegate
没有参数且返回void
的方法正式相同。
如果您查看:https://msdn.microsoft.com/en-us/library/system.action(v=vs.110).aspx,您可以看到:
您可以使用此委托将方法作为参数传递 明确声明自定义委托。
我希望这个例子有所帮助:
public delegate void DelegateMyDeler(); //This is a custom delegate
public class MyClass
{
public DelegateMyDeler MyDeler; //This use your custom delegate
public Action MyVoidAction; // This use Action delegate
}
class MainClass
{
static void Main()
{
// MyClass.MyDeler d = () => Console.WriteLine("my deler"); // Now this is not allowed too!
// d();
// MyClass.MyVoidAction mva1 = () => Console.WriteLine("my void action"); // not allowed, why?
MyClass meClass = new MyClass();
meClass.MyDeler = () => Console.WriteLine("my deler");
meClass.MyDeler();
meClass.MyVoidAction = () => Console.WriteLine("my void action");
meClass.MyVoidAction();
//but you can do (you custom delegate is defined out of the class in this case
//so you have not to add the class prefix):
DelegateMyDeler d = () => Console.WriteLine("my deler 2");
d();
// or
DelegateMyDeler d3 = () => Console.WriteLine("my deler 3");
d3.Invoke();
// and in a real case, for example:
DelegateMyDeler undeterminedMethod;
int x = 3;
switch (x)
{
case 1:
undeterminedMethod = deler1;
break;
case 2:
undeterminedMethod = deler2;
break;
case 3:
undeterminedMethod = deler3;
break;
default:
undeterminedMethod = null;
break;
}
undeterminedMethod?.Invoke(); //In case x is minor than 1 or major than 3, nothing happens
}
static void deler1() { Console.WriteLine("my deler 1"); }
static void deler2() { Console.WriteLine("my deler 2"); }
static void deler3() { Console.WriteLine("my deler 3"); }
}