是否可以从事件中取消订阅匿名方法?
如果我订阅这样的事件:
void MyMethod()
{
Console.WriteLine("I did it!");
}
MyEvent += MyMethod;
Run Code Online (Sandbox Code Playgroud)
我可以这样取消订阅:
MyEvent -= MyMethod;
Run Code Online (Sandbox Code Playgroud)
但是如果我使用匿名方法订阅:
MyEvent += delegate(){Console.WriteLine("I did it!");};
Run Code Online (Sandbox Code Playgroud)
是否有可能取消订阅这种匿名方法?如果是这样,怎么样?
好吧,所以这更像是一个答案而不是一个问题,但在提出这个问题之后,将Dustin Campbell,Egor的各个部分以及" IObservable/Rx/Reactive框架 "中的最后一个提示拉到一起,我想我为这个特殊问题制定了可行的解决方案.它可能会被IObservable/Rx/Reactive框架完全取代,但只有经验才会显示出来.
我故意创造了一个新问题,给我空间来解释我如何得到这个解决方案,因为它可能不会立即显而易见.
有很多相关的问题,大多数人告诉你,如果你想以后能够分离它们,你就不能使用内联lambda:
确实,如果您希望以后能够分离它们,您需要保留对lambda的引用.但是,如果您只是希望事件处理程序在订阅者超出范围时自行分离,则此答案适合您.
说如果我听一个事件:
Subject.NewEvent += delegate(object sender, NewEventArgs e)
{
//some code
});
Run Code Online (Sandbox Code Playgroud)
现在我如何取消注册此活动?或者只是让内存泄漏?
我有以下代码让GUI响应集合中的更改.
myObservableCollection.CollectionChanged += ((sender, e) => UpdateMyUI());
Run Code Online (Sandbox Code Playgroud)
首先,这是一个很好的方法吗?
第二:取消订阅此活动的代码是什么?它是相同的但是 - =(然后又是完整的匿名方法)?
我使用Resharper 5.1代码分析很多次我从resharper得到一个评论
"通过匿名代表取消订阅"
#Part of Code
if (((bool)e.NewValue))
{
listView.PreviewTextInput += (o,args) =>
listView_PreviewTextInput(o,args,listView);
}
else
{
listView.PreviewTextInput -= (o, args) =>
listView_PreviewTextInput(o, args, listView);
}
Run Code Online (Sandbox Code Playgroud)
我怎么能纠正或优化这件事
在发现lambda表达式及其作为匿名函数的用法之后,我发现自己编写了许多更为琐碎的事件,例如:
txtLogin.GotFocus += (o, e) =>
{
txtLogin.Text = string.Empty;
txtLogin.ForeColor = SystemColors.ControlText;
};
txtLogin.LostFocus += (o, e) =>
{
txtLogin.Text = "Login...";
txtLogin.ForeColor = SystemColors.InactiveCaptionText;
};
Run Code Online (Sandbox Code Playgroud)
我也离开了只调用其他函数的事件处理程序,用小lambda代替它们:
backgroundWorker.DoWork += (o, e) => DatabaseLookup.Open(e.Argument as string);
Run Code Online (Sandbox Code Playgroud)
我发现了一些类似的问题来解决性能问题,并指出你无法删除它们,但我还没有发现任何解决这个简单问题的问题这是个好主意吗?
使用lambdas是否被认为是一种良好的形式,或者更多的经验是程序员瞧不起这个?它是否在难以找到的位置隐藏事件处理程序,还是通过减少普通事件处理程序的数量来使代码成为服务?
可能重复:
C#:如何删除lambda事件处理程序
是否可以删除作为匿名函数附加的事件处理程序?假设我有一个事件,我以这种方式订阅它:
TestClass classs = new TestClass ();
classs.myCustomEvent += (a,b) => { Console.Write(""); };
Run Code Online (Sandbox Code Playgroud)
有可能以某种方式使用 - = ??删除此eventHandler
为什么这个声明+赋值会导致错误:
// Use of unassigned local variable 'handler'.
SessionEndingEventHandler handler = (sender, e) => { isShuttingDown = true; SystemEvents.SessionEnding -= handler; };
Run Code Online (Sandbox Code Playgroud)
虽然这不是:
SessionEndingEventHandler handler = null;
handler = (sender, e) => { isShuttingDown = true; SystemEvents.SessionEnding -= handler; };
Run Code Online (Sandbox Code Playgroud)
直观地说,第一个语句应该导致错误但不能立即清楚为什么第二个语句不是.
此外,SystemEvents.SessionEnding在调用之后,如何判断事件是否实际上已取消订阅handler(null, null)?该GetInvocationList只适用于委托.
SystemEvents.SessionEnding += handler;
handler(null, null);
Run Code Online (Sandbox Code Playgroud) 这两个实现之间有区别吗?
1:
public class SMSManager : ManagerBase
{
private EventHandler<SheetButtonClickEventArgs> _buttonClickevent;
public SMSManager(DataBlock smsDataBlock, DataBlock telephonesDataBlock) :
base(smsDataBlock)
{
_buttonClickevent = new EventHandler<SheetButtonClickEventArgs>(OnButtonClick);
SheetEvents.ButtonClick += _buttonClickevent;
}
public override void Dispose()
{
base.Dispose();
if (_buttonClickevent != null)
SheetEvents.ButtonClick -= _buttonClickevent;
}
}
Run Code Online (Sandbox Code Playgroud)
2:
public class SMSManager : ManagerBase
{
public SMSManager(DataBlock smsDataBlock, DataBlock telephonesDataBlock) :
base(smsDataBlock)
{
SheetEvents.ButtonClick += new EventHandler<SheetButtonClickEventArgs>(OnButtonClick);
}
public override void Dispose()
{
base.Dispose();
SheetEvents.ButtonClick -= new EventHandler<SheetButtonClickEventArgs>(OnButtonClick);
}
}
Run Code Online (Sandbox Code Playgroud)
关于内存泄漏,第一个似乎比第二个更正确.但它真的是对的吗?
我一直在阅读这篇MSDN文章和这个问题,试图理解.NET中的事件.不幸的是,它没有点击我,我遇到了很多麻烦.我正在尝试将这项技术整合到我的项目中,但收效甚微.
基本上,我有这个类会读数字.每当遇到一个新号码时,我希望它触发一个名为numberChanged的事件.
所以,我设置了我的活动public event EventHandler numberChanged;.稍后,当我遇到一个与前一个数字不同的数字时,我会触发它.
if(currentNumber != previousNumber){
if(numberChanged != null){
numberChanged(this, new EventArgs());
}
}
Run Code Online (Sandbox Code Playgroud)
但后来我遇到了麻烦'subcibing'这个事件.如果我这样做numberChanged += [something to do here]错误,说numberChanged是一个事件而不是一个类型.
我的解释是否足够明确,可以提供一些建议?非常感谢.
我在找出一种取消订阅的方法时遇到了一些麻烦,这种方法取消了我在预先制作的帮助文件中发现的一些匿名委托事件,这些文件有助于在运行时移动控件.我想取消订阅这些事件的原因是控件(在这种情况下是按钮)将再次被锁定而无法移动.这是helper类中的方法:
public static void Init(Control control)
{
Init(control, Direction.Any);
}
public static void Init(Control control, Direction direction)
{
Init(control, control, direction);
}
public static void Init(Control control, Control container, Direction direction)
{
bool Dragging = false;
Point DragStart = Point.Empty;
control.MouseDown += delegate(object sender, MouseEventArgs e)
{
Dragging = true;
DragStart = new Point(e.X, e.Y);
control.Capture = true;
};
control.MouseUp += delegate(object sender, MouseEventArgs e)
{
Dragging = false;
control.Capture = false;
};
control.MouseMove += delegate(object sender, MouseEventArgs e)
{ …Run Code Online (Sandbox Code Playgroud) 我需要有人帮我解决这个小问题.这是一段代码片段:
void shuffle()
{
for (int i = 0; i < 4; i++) {
// here should be the computations of x and y
buttons[i].Click += (s, e) => { show_coordinates(x, y); };
// shuffling going on
}
}
void show_coordinates(int x, int y)
{
MessageBox.Show(x + " " + y);
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,每次运行循环时,我都会为每个按钮创建一个具有不同x和y的新事件处理程序.在我的表单中有另一个按钮,随机地按下按钮.
所以这就是问题所在:如果我按下随机按钮说10次,然后按任意洗牌按钮,事件处理程序就会叠加,我会得到10个显示x和y值的消息框.
那么每次按shuffle时,如何用新的事件处理程序覆盖前一个事件处理程序.
提前致谢.