C# 简单委托(delegate)与多播委托
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2192219/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simple Delegate (delegate) vs. Multicast delegates
提问by A9S6
I have gone through many articles but I am still not clear about the difference between the normal delegates that we usually create and multicast delegates.
我看了很多文章,但我仍然不清楚我们通常创建的普通委托和多播委托之间的区别。
public delegate void MyMethodHandler(object sender);
MyMethodHandler handler = new MyMethodHandler(Method1);
handler += Method2;
handler(someObject);
The above delegate MyMethodHandler will call these two methods. Now where does multicast delegates come in. I have read that they can call multiple methods but I am afraid that my basic understanding about delegates is not correct.
上面的委托 MyMethodHandler 会调用这两个方法。现在多播委托从哪里进来。我已经读到他们可以调用多个方法,但我担心我对委托的基本理解是不正确的。
采纳答案by Darin Dimitrov
This articleexplains it pretty well:
这篇文章很好地解释了它:
delegate void Del(string s);
class TestClass
{
static void Hello(string s)
{
System.Console.WriteLine(" Hello, {0}!", s);
}
static void Goodbye(string s)
{
System.Console.WriteLine(" Goodbye, {0}!", s);
}
static void Main()
{
Del a, b, c, d;
// Create the delegate object a that references
// the method Hello:
a = Hello;
// Create the delegate object b that references
// the method Goodbye:
b = Goodbye;
// The two delegates, a and b, are composed to form c:
c = a + b;
// Remove a from the composed delegate, leaving d,
// which calls only the method Goodbye:
d = c - a;
System.Console.WriteLine("Invoking delegate a:");
a("A");
System.Console.WriteLine("Invoking delegate b:");
b("B");
System.Console.WriteLine("Invoking delegate c:");
c("C");
System.Console.WriteLine("Invoking delegate d:");
d("D");
}
}
/* Output:
Invoking delegate a:
Hello, A!
Invoking delegate b:
Goodbye, B!
Invoking delegate c:
Hello, C!
Goodbye, C!
Invoking delegate d:
Goodbye, D!
*/
回答by Eric Lippert
The C# specification states that all delegate types must be convertible to System.Delegate
. In fact the way the implementation implements this is that all delegate types are derived from System.MulticastDelegate
, which in turn derives from System.Delegate
.
C# 规范规定所有委托类型都必须可转换为System.Delegate
. 事实上,实现实现这一点的方式是所有委托类型都派生自System.MulticastDelegate
,而后者又派生自System.Delegate
.
Is that clear? I'm not sure that answered your question.
明白了吗?我不确定是否回答了您的问题。
回答by MikeM
"All delegate instances have multicast capability." - http://msdn.microsoft.com/en-us/library/orm-9780596527570-03-04.aspx
“所有委托实例都具有多播功能。” - http://msdn.microsoft.com/en-us/library/orm-9780596527570-03-04.aspx
"In C#, all delegate types support multicast" - http://msdn.microsoft.com/en-us/library/orm-9780596516109-03-09.aspx
“在 C# 中,所有委托类型都支持多播” - http://msdn.microsoft.com/en-us/library/orm-9780596516109-03-09.aspx
回答by Lea Yates
Sorry for adding to somebody else's answer but I thought that delegates are called in the order they are added.
很抱歉添加到其他人的答案中,但我认为代表是按添加顺序调用的。
"Multicast Delegates" section
“组播委托”部分
http://msdn.microsoft.com/en-us/library/orm-9780596527570-03-04.aspx
http://msdn.microsoft.com/en-us/library/orm-9780596527570-03-04.aspx
回答by JacquesB
To clarify a bit: Alldelegates are instances of the class MulticastDelegate
, regardless of whether they have one or multiple target methods. In principle there are no difference between a delegate with a single or multiple targets, although the runtime is optimized a bit towards the common case with a single target. (A delegate with 0 targets is not possible though, it is one or more.)
澄清一点:所有委托都是 class 的实例MulticastDelegate
,无论它们是否具有一个或多个目标方法。原则上,具有单个或多个目标的委托之间没有区别,尽管运行时针对具有单个目标的常见情况进行了一些优化。(虽然不可能有 0 个目标的委托,它是一个或多个。)
When you are instantiating a delegate like new MyMethodHandler(Method1)
, you create a delegate with a single target (the Method1
method).
当您实例化像 那样的委托时new MyMethodHandler(Method1)
,您将创建一个具有单个目标(Method1
方法)的委托。
Delegates with multiple targets are created by combining two existing delegates. The resulting delegate will have the sum of targets. Delegates can be combined explicitly with Delegate.Combine()
, but also implicitly by using the +=
operator on an existing delegate, as in your example.
具有多个目标的委托是通过组合两个现有委托来创建的。生成的委托将具有目标的总和。委托可以与 显式组合Delegate.Combine()
,但也可以通过+=
在现有委托上使用运算符隐式组合,如您的示例所示。
Invoking a delegate in turn calls every target in the delegate. So in your example handler(someObject);
will call two methods (Method1
and Method2
), since you have created a delegate with these two targets.
调用委托依次调用委托中的每个目标。因此,在您的示例handler(someObject);
中将调用两个方法 (Method1
和Method2
),因为您已经使用这两个目标创建了一个委托。
回答by Suraj
A multicast delegate is a delegate that has references to more than one function. When you invoke a multicast delegate, all the functions the delegate is pointing to, are invoked.
多播委托是引用多个函数的委托。当您调用多播委托时,委托指向的所有函数都会被调用。
Type 1:
类型 1:
0 argument and void return type delegate -
0 参数和 void 返回类型委托 -
Method 1 -
方法 1 -
using System;
delegate void SampleDelegate (); //A delegate with 0 argument and void return type is declared
class MainClass
{
public static void Main ()
{
SampleDelegate Del1 = new SampleDelegate (Message1); //Del1 declared which points to function Message1
SampleDelegate Del2 = new SampleDelegate (Message2); //Del2 declared which points to function Message2
SampleDelegate Del3 = new SampleDelegate (Message3); //Del3 declared which points to function Message3
SampleDelegate Del4 = Del1 + Del2 + Del3; //Del4 declared which points to function Message4
//Del4 is then initialized as sum of Del1 + Del2 + Del3
Del4 (); //Del4 is invoked;
//Del4 in turn invokes Del1, Del2 and Del3 in the same order they were initialized to Del4
//Del1, Del2, Del3 in turn invokes their respective functions to which they point to
//The three functions Message1, Message2 and Message3 gets executed one after another
}
//Output:
//This is message 1
//This is message 2
//This is message 3
Del4 - Del1; //Removes Del1 from Del4
Del4();
//New Output:
//This is message 2
//This is message 3
Del4 + Del1; //Again adds Del1 to Del4
Del4();
//New Output:
//This is message 1
//This is message 2
//This is message 3
public static void Message1 () //First sample function matching delegate signature
{
Console.WriteLine ("This is message 1");
}
public static void Message2 () //Second sample function
{
Console.WriteLine ("This is message 2");
}
public static void Message3 () //Third sample function
{
Console.WriteLine ("This is message 3");
}
}
Method 2-
方法 2-
using System;
delegate void SampleDelegate ();
class MainClass
{
public static void Main ()
{
SampleDelegate del = new SampleDelegate (Message1); //Declares del and initializes it to point to method Message1
del += Message2; //Now method Message2 also gets added to del. Del is now pointing to two methods, Message1 and Message2. So it is now a MultiCast Delegate
del += Message3; //Method Message3 now also gets added to del
del (); //Del invokes Message1, Message2 and Message3 in the same order as they were added
/*
Output:
This is Message1
This is Message2
This is Message3
*/
del -= Message1; //Method Message1 is now removed from Del. It no longer points to Message1
//Del invokes the two remaining Methods Message1 and Message2 in the same order
del ();
/*
New Output:
This is Message2
This is Message3
*/
del += Message4; //Method Message4 gets added to Del. The three Methods that Del oints to are in the order 1 -> Message2, 2 -> Message3, 3 -> Message4
//Del invokes the three methods in the same order in which they are present.
del ();
/*
New Output:
This is Message2
This is Message3
This is Message4
*/
}
public static void Message1 ()
{
Console.WriteLine ("This is Message1");
}
public static void Message2 ()
{
Console.WriteLine ("This is Message2");
}
public static void Message3 ()
{
Console.WriteLine ("This is Message3");
}
public static void Message4 ()
{
Console.WriteLine ("This is Message4");
}
}
Type 2:
类型 2:
0 arguments and int return type delegate
0 个参数和 int 返回类型委托
Method 1-
方法1-
using System;
delegate int SampleDelagate ();
class MainClass
{
public static void Main ()
{
SampleDelagate del1 = new SampleDelagate (Method1);
SampleDelagate del2 = new SampleDelagate (Method2);
SampleDelagate del3 = new SampleDelagate (Method3);
SampleDelagate del4 = del1 + del2 + del3;
int ValueReturned = del4 ();
//Del4 invokes Del1, Del2, Del3 in the same order. Here the return type is int. So the return of last delegate del3 is returned. Del3 points to Method3. So returned value is 3.
Console.WriteLine (ValueReturned);
//Output: 3
}
public static int Method1 ()
{
return 1;
}
public static int Method2 ()
{
return 2;
}
public static int Method3 ()
{
return 3;
}
}
Method 2-
方法2-
Same process as Type 1
与类型 1 相同的过程
So when there is a return type of a MultiCast Delegate the return value is the return value of last delegate.
所以当有一个 MultiCast Delegate 的返回类型时,返回值是最后一个委托的返回值。
Type 3:
类型 3:
int, int, ref int arguments and void return type delegate -
int, int, ref int 参数和 void 返回类型委托 -
using System;
delegate void SampleDelegate (ref int SampleReferenceParameter);
class MainClass
{
public static void Main ()
{
SampleDelegate del1, del2, del3, del4;
del1 = new SampleDelegate (SampleMethodOne);
del2 = new SampleDelegate (SampleMethodTwo);
del3 = new SampleDelegate (SampleMethodTwo);
del4 = del1 + del2 + del3 - del3;
int SampleReferenceParameterValue = 0;
del4 (ref SampleReferenceParameterValue);
Console.WriteLine (SampleReferenceParameterValue);
}
public static void SampleMethodOne (ref int SampleReferenceParameter)
{
SampleReferenceParameter = 1;
}
public static void SampleMethodTwo (ref int SampleReferenceParameter)
{
SampleReferenceParameter = 2;
}
public static void SampleMethodThree (ref int SampleReferenceParameter)
{
SampleReferenceParameter = 3;
}
}
/*
Here del4 is first set as sum of del1, del2 and del3. Then del3 is subtracted from del4. So del4 now has del1, del2.
When del4 is invoked, first del1 and then del2 is invoked.
del1 sets reference parameter to 1. del2 sets reference parameter to 2.
But since del2 is called last final value of reference parameter is 2
*/