Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.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#_Events_Lambda_Delegates - Fatal编程技术网

C# 将操作作为参数传递不允许订阅它

C# 将操作作为参数传递不允许订阅它,c#,events,lambda,delegates,C#,Events,Lambda,Delegates,以下是测试类: public class TestClass { private readonly Action _action; public TestClass() { _action += () => { Console.WriteLine("1"); }; Subscribe(_action); _action?.Invoke(); } private static void Subscri

以下是测试类:

public class TestClass
{
    private readonly Action _action;

    public TestClass()
    {
        _action += () => { Console.WriteLine("1"); };
        Subscribe(_action);
        _action?.Invoke();
    }

    private static void Subscribe(Action action)
    {
        action += () => { Console.WriteLine("2"); };
    }
}
运行时,不会打印“2”,因为不会调用订阅操作的lambda

在我看来,当将一个操作作为参数传递时,它是按值传递的(C++中的术语),因此对+=操作符的调用发生在另一个动作实例上。


如何将操作作为参数传递,以便以后可以使用+=运算符订阅它。或者使用操作对此无效?

原因是,当编译器看到带有委托的
+=
运算符时,它使用
委托。组合
方法以连接委托的调用列表,并返回新委托

如果调用
Console.WriteLine(action.GetHashCode()),可以检查它运算符的前后

因此,实际上您正试图通过将新值分配给内部范围(方法范围变量)中的变量来更改外部范围中的变量

说明:

当我们将
Action
delegate作为参数传递时,它会创建一个方法范围的变量,并将对该委托的引用放入其中。稍后,当我们调用
+=
运算符时,它返回一个新引用,并将其分配给同一个方法作用域变量。此时,它指向另一个对象,而原始的
\u action
变量仍指向初始对象

如果要为在方法范围之外创建的变量分配新值并更改其指针,可以使用
ref
关键字通过引用传递它。这将向编译器指示参数是通过引用传递的,而不是通过值传递的:

private static void Subscribe(ref Action action)
{
    action += () => { Console.WriteLine("2"); };
}

传递对您的场景不起作用吗?
action+=()=>{Console.WriteLine(“2”);}
action=action+()=>{Console.WriteLine(“2”);}
因此,您实际上正在创建一个新操作,并且该新操作从未离开
订阅
的范围,因此,结合前面的两条注释似乎意味着将
Subcribe
方法更改为
void Subscribe(ref action action)
可能会起作用。您将传入一个操作,引用将被修改为现在有两个委托的新操作,并传递回调用方(通过
Subscribe(ref\u action);