You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中Lambda表达式可访问myRect,传统方法却无法访问的原因咨询

为什么Lambda能访问myRect,而传统事件处理方法不行?

这事儿核心是**C#闭包(Closure)**的特性,以及局部变量作用域的限制,咱们掰开揉碎了说:

1. Lambda的闭包帮你"抓住"了myRect

当你写SB.Completed += (s,e) => myCanvas.Children.Remove(myRect);的时候,这个Lambda表达式形成了一个闭包——它会把当前myCanvas_MouseMove方法里的局部变量myRect的引用"捕获"下来,哪怕myCanvas_MouseMove方法执行完退出了,这个引用也会被保留,直到Completed事件触发。

换句话说:每次鼠标移动生成新的myRect和对应的Storyboard时,这个Lambda就绑定到了当前这一个特定的myRect实例上,等动画跑完,它能精准找到要移除的那个矩形,不会搞混。

2. 传统事件方法看不到局部变量myRect

你的SB_Completed是类级别的方法,它不在myCanvas_MouseMove的局部作用域里——局部变量的作用域只限于定义它的方法内部,类的其他方法根本没权限直接访问这个变量。

你现在用myCanvas.Children.RemoveAt(0)其实是凑合用,但风险很大:如果同时有多个动画在运行,你移除的大概率不是刚完成动画的那个矩形,很容易出bug。

那传统方法怎么精准拿到对应的myRect?

不想用Lambda也没关系,你可以通过Storyboard的Tag属性把目标矩形存起来:

// 在绑定事件前,把myRect存到Storyboard的Tag里
SB.Tag = myRect;
SB.Completed += new EventHandler(SB_Completed);

然后在SB_Completed里取出来使用:

void SB_Completed(object sender, EventArgs e) {
    Storyboard finishedSB = sender as Storyboard;
    // 先做安全校验,避免空引用
    if (finishedSB?.Tag is Rectangle targetRect) {
        myCanvas.Children.Remove(targetRect);
    }
}

这样就能和Lambda一样,精准移除对应的那个矩形了。

小额外提示

你的代码里每次MouseMove都新建Random Rand = new Random();其实有坑——Random默认用系统时钟当种子,短时间内多次创建会导致生成的随机数重复。建议把Random实例提到类的字段里,比如:

// 把Random定义成类的成员变量,只初始化一次
private Random _rand = new Random();

然后在方法里直接用_rand.Next(256)就行,这样生成的颜色会更随机~

内容的提问来源于stack exchange,提问作者Himanshu Mange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:30:07