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);