c# - .NET Delegate 作为参数传递问题

标签 c# delegates

对作为参数传递的 C# 委托(delegate)感到困惑:

class Program
{
    static void Main(string[] args)
    {
        var a = new A();
        Action holder = delegate{};
        //a.Attach1(holder); //nothing printed
        a.Attach2(ref holder);//print as expected

        holder();
    }
}

public class A
{
    private void P1()
    {
        Console.WriteLine("Inaccessible");
    }
    public void P2()
    {
        Console.WriteLine("Accessible");
    }
    public void Attach1(Action holder)
    {
        holder += P1;
        holder += P2;
    }
    public void Attach2(ref Action holder)
    {
        holder += P1;
        holder += P2;
    }
}

delegate 是引用类型,为什么还需要像 Attach2 中那样用字体中的 ref 传递才能正常工作,类似于值类型?

从 C++ 的经验来看,委托(delegate)只是一个函数指针,Attach1(Action holder) 类似于 Attach1(Action* holder),原始持有者作为“值”传递,因此未分配,而在第二种情况下,Attach2 (ref Action holder) 类似于 Attach1(Action** holder),实际传递的是指针,因此可以正确操作。但是为什么在 .NET 中没有指示或提示???

最佳答案

因为委托(delegate)实例是不可变,而+=是对委托(delegate)实例的新赋值;它基本上是:

holder = (Action)Delegate.Combine(holder, P1);
holder = (Action)Delegate.Combine(holder, P2);

如果您不将其作为 ref 传递,则在方法之外将看不到新值。

或者用更简单的术语来说——考虑一个stringstring 同样是不可变的,+= 是一个赋值。现在考虑:

public void Append(string s) {
    s += "[suffix]";
}
public void Append2(ref string s) {
    s += "[suffix]";
}

如果我们调用:

string x = "abc";
Append(x);
Console.WriteLine(x);

我们将看到abc。如果我们调用

string x = "abc";
Append2(ref x);
Console.WriteLine(x);

我们将看到 abc[suffix] - 出于完全相同的原因

关于c# - .NET Delegate 作为参数传递问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16957796/

相关文章:

c# - .NET 中的彩色图像量化

swift - 使用 NSURLSession 下载委托(delegate)(IOS,swift)

macos - 使用 Swift "why"做一些委托(delegate)函数需要覆盖 func

c# - BeginInvoke 抛出异常

c# - 使用 ILGenerator 创建委托(delegate)

C# 自定义属性备选方案

c# - 该进程无法访问该文件,因为它正被另一个进程使用

c# - Application Insights 的日志未写入跟踪日志

c# - 更复杂(现实生活)的模型绑定(bind)?

ios - 设置 UIAlertView 委托(delegate)