我经常想写这样的东西:
new Form
{
Text = "Caption",
Controls =
{
new Button { Text = "Button 1", Click = (s, e) => MessageBox.Show("Button 1 Clicked"), Location = new Point(10, 10) },
new Button { Text = "Button 2", Click = new EventHandler(Button2Clicked), Location = new Point(10, 40) },
new Button { Text = "Button 3", Click = Button3Clicked, Location = new Point(10, 70) },
},
}
初始化器语法只是糖,为什么编译器无法弄清楚如何为事件订阅生成代码?
给我一些糖,宝贝!
当发明初始化语法时,有人必须考虑事件并拒绝它们。我一直试图想象理由可能是什么,并且空白。
是因为事件是一个可能有多个订阅者的多播对象吗?不,这是一个初始化过程;没有其他订阅者。 [更新] 不正确,初始化程序在构建后应用,对象可以subscribe to its own events。
给Eric的一个注释:我听说过为什么C#没有实现功能X 语音。在这种情况下,有人已经在那里,实现初始化器。
更新
似乎存在争用/混淆,因为我在我的示例中使用了Click =
。实际语法与问题无关。它可以很容易地成为Click +=
,它反映了你必须正常添加处理程序的方式。我更喜欢前者,因为它与初始化器语法的其余部分一致,但最终我并不关心,只要我能订阅初始化列表中的事件。
另一次更新
我确实意识到现在添加该功能可能性不大。想到的第一个问题是Intellisense必须更新。现在可能有很多其他因素会妨碍添加此功能。我的问题是:他们为什么不首先添加它。肯定有一些令人信服的东西可以证明“不可能”的投票。
答案 0 :(得分:6)
我看不出有什么理由说他们不能提供这小茶匙糖,我猜他们只是没有!
事件中已经涉及很多语法糖,如果只是在没有提供自己的实现的情况下在类上声明事件,编译器会为您提供委托支持字段,以及添加/删除'方法'实现。此外,当您添加事件处理程序时,编译器使用委托推理,允许您简单地指向方法,而不是创建表示方法的委托。
有趣的是,Mono C#允许您在对象初始值设定项中添加事件处理程序:
http://tirania.org/blog/archive/2009/Jul-27-1.html
切换到Mono的时间; - )
答案 1 :(得分:2)
尝试简单地分配一个事件:
Click = (o,e) => { <CODE> }
不起作用。初始化程序仅适用于您可以直接分配的内容。这是因为事件需要能够通知他们想要的任何人(不应该允许你在事故中删除别人对该事件的注册)。
我不确定这是否是他们的推理,但它对我有用。
答案 2 :(得分:2)
fields 和 events 之间存在很大差异。有一篇很好的文章here概述了这些差异,但这就是你的问题的答案:可以为一个字段分配一个值;一个事件看起来像一个领域,但是一个非常不同的野兽。
修改强>
从我链接的文章:
我们已经看到event关键字是委托声明的修饰符,它允许它包含在接口中,从声明它的类中约束它的调用,为它提供一对可自定义的访问器(添加和删除),并强制委托签名
请记住,event
是一种捷径;在幕后,编译器使用add()
和remove()
方法创建对象。像:
public class Button {
public event EventHandler Click {
void add {...}
void remove {...}
}
}
也许这会提供一些见解......:
Button btn = new Button {Click += (s, e) => MessageBox.Show("hello")};
您收到的错误消息是“无法使用集合初始值设定项初始化类型'Button',因为它没有实现IEnumerable”
还有一点需要注意......如果你从表单中分配事件处理程序,你可以这样做:
this.button1.Click += (s, e) => this.textBox1.Text = e.ToString();
您无法从您创建的代码中访问表单变量。我得到你来自哪里,我不同意......你正在做什么可以成功。我想我的观点是,为什么决定不使其成功。
答案 3 :(得分:1)
但是,这是一个棘手的解决方法,可让您订阅初始化列表中的事件......
public class TestClass
{
public class MyButton : Button
{
public EventHandler ClickSubscriber
{
get { return null; }
set { Click += value; }
}
}
public static void RunTest()
{
new Form
{
Text = "Caption",
Controls =
{
new MyButton
{
ClickSubscriber = (s, e) =>
MessageBox.Show("Button 1 Clicked"),
},
},
};
}
}