Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 关于代表的澄清_C#_.net_Delegates - Fatal编程技术网

C# 关于代表的澄清

C# 关于代表的澄清,c#,.net,delegates,C#,.net,Delegates,下面的代码在做什么?我想指针将改为乘法方法。 但是“+=”在这里做什么呢。我很困惑 delegate int calc(int a , int b); static void Main(string[] args) { calc c = new calc(Add); c += new calc(Multiply); Console.WriteLine(c(3, c(4, 2))); Console.Read

下面的代码在做什么?我想指针将改为乘法方法。 但是“+=”在这里做什么呢。我很困惑

    delegate int calc(int a , int b);

    static void Main(string[] args)
    {
        calc c = new calc(Add);
        c += new calc(Multiply);
        Console.WriteLine(c(3, c(4, 2)));
        Console.Read();
    }

    public static int Add(int a, int b)
    {
        return (a + b);
    }

    public static int Multiply(int a, int b)
    {
        return (a * b);
    }

+=类似于向委托对象追加多个调用。由于它是一个多播委托,您可以将多个目标调用附加到单个委托。若要附加到委托,需要新的委托对象。这就是我们在第二行所做的

类似于,

CalcDelegate C1, C2;
C1 = new CalcDelegate(Add);
C2 = new CalcDelegate(Multiply);
C1 = C1 + C2;

它被称为。

+和+=运算符

与使用
+
操作符添加值的方式类似,您可以使用
+=
操作符添加和重新分配相同的值

这些运算符应用于
int
s的示例如下:

int a = 5;
a += 7; // a is now 12
a = a + 11;
Console.WriteLine(a);
二十四

组合代理

正如AVD提到的,你

当您将这些运算符应用于代理时,您并不是在进行数学“求和”或“求和并赋值”,就像我在
int
s中的示例一样。相反,您正在修改调用委托时要调用的方法列表

从该条中:

可以组合委托,以便在调用委托时,调用整个方法列表—可能具有不同的目标

因此,当您添加/组合委托时,最终将调用多个方法

如果您将代码更改为:

public static int Add(int a, int b)
{
    Console.WriteLine("From Add");
    return (a + b);
}

public static int Multiply(int a, int b)
{
    Console.WriteLine("From Multiply");
    return (a * b);
}
运行程序时,您将看到以下输出:

从添加
从乘法
从添加
从乘法
二十四

这是因为:

  • 您组合了
    Add
    Multiply
    委托,因此在调用
    c(x,y)
  • Multiply
    是您添加到该代理链的最后一个代理
  • 您正在呼叫
    c(x,y)
    两次。这类似于调用:
    Multiply(3,Multiply(4,2))
从组合代理返回值

文章中还提到了关于您添加到链中的最后一个代理的这一点:

如果一个委托类型被声明为返回一个值(即它不是用void返回类型声明的),并且调用了一个组合委托实例,那么从该调用返回的值就是列表中最后一个简单委托返回的值

添加到链中的最后一个方法是
Multiply
,因此会抛出所有其他返回值,并且在调用
c(x,y)
时只使用
Multiply
中的返回值


您可以在程序中看到这一点<代码>3*4*2是24,这是程序的输出。对
Add
的调用都不会影响最终结果。

您可以将委托视为值类型(如
int
double
)和方法地址数组之间的交叉

您知道,如果您编写此代码:

var x = 5;
var y = x + 2;
y += 3;
然后,在
x==5
y==10
之后,即使
y
的中间值为
7
,但在最终赋值时,该值被“丢弃”

很明显,
y
的最终值不是
3

您在代码中编写了以下内容:

calc c = new calc(Add);
c += new calc(Multiply);
y
一样,
c
的最终值不是
。实际上更像这样:

c == { Add, Multiply }
public static int Add(int a, int b)
{
    Console.WriteLine("Add({0}, {1})", a, b);
    return (a + b);
}

public static int Multiply(int a, int b)
{
    Console.WriteLine("Multiply({0}, {1})", a, b);
    return (a * b);
}
Add(4, 2)
Multiply(4, 2)
Add(3, 8)
Multiply(3, 8)
24
然后,当您调用类似于
c(4,2)
的函数时,实际上是在调用这两个函数
Add
Multiply
,因为委托返回一个值,所以您只会返回最终委托的值—在本例中是从
Multiply
—这就是为什么“指针”看起来像是更改为
乘法
方法

在调用
c
之前,可以尝试添加此代码:

c -= new calc(Multiply);
这将有效地将
c
返回到以下位置:

c == { Add }
这就是为什么委托看起来像是方法地址数组

现在,如果将
Add
Multiply
方法更改为如下所示:

c == { Add, Multiply }
public static int Add(int a, int b)
{
    Console.WriteLine("Add({0}, {1})", a, b);
    return (a + b);
}

public static int Multiply(int a, int b)
{
    Console.WriteLine("Multiply({0}, {1})", a, b);
    return (a * b);
}
Add(4, 2)
Multiply(4, 2)
Add(3, 8)
Multiply(3, 8)
24
然后,您可以在通话发生时观看通话。您的原始代码如下所示:

c == { Add, Multiply }
public static int Add(int a, int b)
{
    Console.WriteLine("Add({0}, {1})", a, b);
    return (a + b);
}

public static int Multiply(int a, int b)
{
    Console.WriteLine("Multiply({0}, {1})", a, b);
    return (a * b);
}
Add(4, 2)
Multiply(4, 2)
Add(3, 8)
Multiply(3, 8)
24

我希望这会有所帮助。

a+=b相当于a=a+位运算符重载语法(其中运算符为+=),用于添加/组合委托。+1此处的最佳响应也正确地说明了返回值来自上次添加的委托。