动作和委托实例化和可访问性之间的区别
Difference between Action and delegate instantiation and accessibility
为什么 MyDeler "static",因为我可以通过 class 名称访问 MyDeler,但我不能明确地说 public "static" delegate void MyDeler( ),也不能通过 MyClass 的实例访问 d,如 new 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?
}
}
感谢帮助!
MyDeler
是 type 声明,不是变量声明。你不能在其中存储东西或分配给它。
要创建用于存储 MyDeler
实例的字段,请将此行添加到 MyClass
:
public MyDeler MyDelerField;
现在可以给它赋值了。
Why is MyDeler "static", as in I can access MyDeler through the class name, but I can't explicity say public "static" delegate void MyDeler(), nor can I access d through an instance of MyClass, as in new MyClass.d()?
MyDeler
的声明在 MyClass
中声明了一个 类型 。它类似于声明任何其他嵌套类型,例如:
class MyClass
{
public class MyNestedClass { }
}
它是 类型 MyClass
的成员,而不是 MyClass
的任何实际实例,甚至 class MyClass
作为 static
成员。
嵌套类型既不是 "instance" 也不是 "static",因为它是 类型系统 的一部分,而不是 class 本身的一部分.
why is it that I have to new up a MyClass to use MyVoidAction?
因为MyVoidAction
是class的成员,并且是实例的成员。因此,您需要拥有 class 的 实例 才能访问它。
the delegate void MyDeler() defines a type, which confuses me because I imagine something like this
您在 public static class DelegateClass
示例中的声明正在做完全不同的事情。 C# 的一个不幸方面是使用 static
来指代各种不同的事物。它不像 Java 中那么糟糕,但它仍然令人困惑(正如您所发现的那样)。
在该声明中,static
一词的使用 而不是 使 DelegateClass
成为包含类型 [=12] 的 "static member" =].相反,单词 static
作为 class
声明的一部分意味着 整个 class 将仅包含 static
个成员。
因此,当您在不使用 static
关键字的情况下声明 DoDel()
时,您试图在您承诺的 class 中声明一个实例成员,即该方法只声明静态成员。如果将 static
添加到方法声明中,它将编译。
并不是说这样做会使该示例中的 DelegateClass
class 类似于另一个示例中的 MyVoidAction
成员。它仍然是一个 type 声明,在 MyClass
class 中声明一个嵌套类型,并且仍然遵循类型规则,而不是 class 成员。但我希望至少能向您解释为什么让您感到困惑的示例会以它的方式工作。
让我们揭开这个神秘面纱:
当你声明 MyDeler
:
public delegate void MyDeler();
您正在做的是定义一种将要执行的方法类型 "delegated"。换句话说,你是说这个签名后面有一个方法,我打算保留对它的引用。为了让编译器识别这些引用,将使用这种类型。
接下来您将需要一个真正的指向该方法的指针,因为这只是您的 "definition"。这就是为什么您需要一个 "MyDeler" 类型的变量,您可以将实际方法分配给该变量来调用:
MyClass.MyDeler d = () => Console.WriteLine("my deler");
这一行表示 "create a variable named d
of type MyClass.MyDeler
that holds a reference to this inline method"。从这里开始,当您调用 d();
时,指针将实际执行内联方法。
对于操作:
public Action MyVoidAction;
您现在正在声明 class 的 public 属性。因此,在使用此 属性.
之前,您需要一个 class 的实例
这里的技巧是 Action 是委托的已知定义。 Microsoft 有一个内置类型,您可以使用它来代替声明您自己的 void MyDeler();
。它本质上是语法糖,但请记住,它仍然是一种类型,因为您已经创建了一个 public 属性,您现在需要为其分配将实际执行的方法,正如我们之前讨论的那样,您需要一个实例:
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!
希望对您有所帮助。
Action
和没有参数的方法的 delegate
和 returns void
在形式上是同一件事。
如果你看一下:https://msdn.microsoft.com/en-us/library/system.action(v=vs.110).aspx 你会看到:
You can use this delegate to pass a method as a parameter without
explicitly declaring a custom delegate.
希望这个例子对您有所帮助:
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"); }
}
为什么 MyDeler "static",因为我可以通过 class 名称访问 MyDeler,但我不能明确地说 public "static" delegate void MyDeler( ),也不能通过 MyClass 的实例访问 d,如 new 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?
}
}
感谢帮助!
MyDeler
是 type 声明,不是变量声明。你不能在其中存储东西或分配给它。
要创建用于存储 MyDeler
实例的字段,请将此行添加到 MyClass
:
public MyDeler MyDelerField;
现在可以给它赋值了。
Why is MyDeler "static", as in I can access MyDeler through the class name, but I can't explicity say public "static" delegate void MyDeler(), nor can I access d through an instance of MyClass, as in new MyClass.d()?
MyDeler
的声明在 MyClass
中声明了一个 类型 。它类似于声明任何其他嵌套类型,例如:
class MyClass
{
public class MyNestedClass { }
}
它是 类型 MyClass
的成员,而不是 MyClass
的任何实际实例,甚至 class MyClass
作为 static
成员。
嵌套类型既不是 "instance" 也不是 "static",因为它是 类型系统 的一部分,而不是 class 本身的一部分.
why is it that I have to new up a MyClass to use MyVoidAction?
因为MyVoidAction
是class的成员,并且是实例的成员。因此,您需要拥有 class 的 实例 才能访问它。
the delegate void MyDeler() defines a type, which confuses me because I imagine something like this
您在 public static class DelegateClass
示例中的声明正在做完全不同的事情。 C# 的一个不幸方面是使用 static
来指代各种不同的事物。它不像 Java 中那么糟糕,但它仍然令人困惑(正如您所发现的那样)。
在该声明中,static
一词的使用 而不是 使 DelegateClass
成为包含类型 [=12] 的 "static member" =].相反,单词 static
作为 class
声明的一部分意味着 整个 class 将仅包含 static
个成员。
因此,当您在不使用 static
关键字的情况下声明 DoDel()
时,您试图在您承诺的 class 中声明一个实例成员,即该方法只声明静态成员。如果将 static
添加到方法声明中,它将编译。
并不是说这样做会使该示例中的 DelegateClass
class 类似于另一个示例中的 MyVoidAction
成员。它仍然是一个 type 声明,在 MyClass
class 中声明一个嵌套类型,并且仍然遵循类型规则,而不是 class 成员。但我希望至少能向您解释为什么让您感到困惑的示例会以它的方式工作。
让我们揭开这个神秘面纱:
当你声明 MyDeler
:
public delegate void MyDeler();
您正在做的是定义一种将要执行的方法类型 "delegated"。换句话说,你是说这个签名后面有一个方法,我打算保留对它的引用。为了让编译器识别这些引用,将使用这种类型。
接下来您将需要一个真正的指向该方法的指针,因为这只是您的 "definition"。这就是为什么您需要一个 "MyDeler" 类型的变量,您可以将实际方法分配给该变量来调用:
MyClass.MyDeler d = () => Console.WriteLine("my deler");
这一行表示 "create a variable named d
of type MyClass.MyDeler
that holds a reference to this inline method"。从这里开始,当您调用 d();
时,指针将实际执行内联方法。
对于操作:
public Action MyVoidAction;
您现在正在声明 class 的 public 属性。因此,在使用此 属性.
之前,您需要一个 class 的实例这里的技巧是 Action 是委托的已知定义。 Microsoft 有一个内置类型,您可以使用它来代替声明您自己的 void MyDeler();
。它本质上是语法糖,但请记住,它仍然是一种类型,因为您已经创建了一个 public 属性,您现在需要为其分配将实际执行的方法,正如我们之前讨论的那样,您需要一个实例:
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!
希望对您有所帮助。
Action
和没有参数的方法的 delegate
和 returns void
在形式上是同一件事。
如果你看一下:https://msdn.microsoft.com/en-us/library/system.action(v=vs.110).aspx 你会看到:
You can use this delegate to pass a method as a parameter without explicitly declaring a custom delegate.
希望这个例子对您有所帮助:
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"); }
}