在C#中为什么不能我通过其他类的事件处理程序的参考,我怎么能围绕它得到什么? [英] In C# why can't I pass another class' EventHandler reference and how can I get around it?
问题描述
如果我有ClassA的,有一个公共事件,SomeEvent和ClassC有方法的addListener,接受一个事件处理程序的参考,为什么不能ClassB的有这样一行c.addListener(REF a.SomeEvent)?如果我试试我得到一个说:编译错误:该事件'ClassA.SomeEvent只能出现在左手侧+ =或 - =(从类型ClassA的'内使用时除外)
。为什么这个限制存在?又如何,我可以避开它,同时保持合理的接近我的结构?
我一个C#新手;!任何帮助,将不胜感激谢谢
类ClassA的{
公共事件的EventHandler SomeEvent;
}
ClassB的{
公共ClassB的(){
ClassA的一个=新ClassA的();
ClassC C =新ClassC();
c.addListener(REF a.SomeEvent); //编译错误
}
}
类ClassC {
公共无效的addListener(REF事件处理程序处理程序){
+处理器=的onEvent;
}
私人无效的onEvent(对象发件人,EventArgs五){
//做的东西
}
}
本次活动的关键字创建对于私人委托对象的访问。属性不完全一样的东西,它限制进入私人领域。您的代码段失败,出现类似错误的类型,当你使用一个属性,而不是一个事件:
类ClassA的{
酒店的公共int属性{搞定;组; }
}
级ClassB的{
公共ClassB的(){
ClassA的一个=新ClassA的();
ClassC C =新ClassC();
c.setValue(REF a.Property); // CS0206
}
}
类ClassC {
公共无效的setValue(REF int值){
值= 42;
}
}
这是比较容易看到现在,也没办法编译器,以确保setValue()方法使用属性setter。它也可以知道,价值的说法是一个二传手或纯场的属性。
这是一个事件不太清楚,因为有这么多的语法糖工作中。该声明
公共事件的EventHandler SomeEvent;
实际生成代码:
私人事件处理_SomeEvent;
公共事件SomeEvent {
加{_SomeEvent + =新的EventHandler(值); }
拆下{_SomeEvent - =新的EventHandler(值); }
}
添加和删除访问器相当于一个get和set访问财产,他们阻止代码与私人领域_SomeEvent搞乱。按照惯例,add访问当您使用+ =调用,取出被调用, - =。与前面的例子我给一个属性进行比较。同样的问题,您不能使用ref关键字和ClassC.addListener()将没有办法知道,处理器实际上是一个事件,而不是一个委托对象。如果编译器传递_SomeEvent相反,使用访问点丢失
您可以通过重构代码来解决这个问题:
类ClassC {
公共事件处理getListener(){
返回新的EventHandler(的onEvent);
}
私人无效的onEvent(对象发件人,EventArgs五){}
}
...
a.SomeEvent + = c.getListener();
最后要注意的:事件之间的对称性和一个属性是有点失落,C#编译器自动生成的添加/删除访问,如果你不把它们明确写入。它不为一个属性做到这一点。它会作出自动属性轻松了许多:
属性int属性;
但是,这将需要添加一个新的关键字的语言,一些C#团队真的不喜欢。就像VB.NET和C ++ / CLI等语言的确有这个关键字。
If I have ClassA that has a public event, SomeEvent, and ClassC that has method, addListener, that accepts an EventHandler reference, why can't ClassB have a line that says c.addListener(ref a.SomeEvent)? If I try I get a compiler error that says: "The event 'ClassA.SomeEvent' can only appear on the left hand side of += or -= (except when used from within the type 'ClassA').
Why does this restriction exist? And how can I get around it while staying reasonably close to my structure?
I'm a C# newbie; any help would be appreciated. Thanks!
class ClassA {
public event EventHandler SomeEvent;
}
ClassB{
public ClassB() {
ClassA a = new ClassA();
ClassC c = new ClassC();
c.addListener(ref a.SomeEvent); //Compile error
}
}
class ClassC {
public void addListener(ref EventHandler handler) {
handler += onEvent;
}
private void onEvent(object sender, EventArgs e) {
//do stuff
}
}
The event keyword creates an accessor for a private delegate object. The exact same thing a property does, it restricts access to a private field. Your code snippet fails with a similar kind of error when you use a property instead of an event:
class ClassA {
public int Property { get; set; }
}
class ClassB {
public ClassB() {
ClassA a = new ClassA();
ClassC c = new ClassC();
c.setValue(ref a.Property); // CS0206
}
}
class ClassC {
public void setValue(ref int value) {
value = 42;
}
}
It is easier to see now, there is no way for the compiler to ensure that the setValue() method uses the property setter. Nor could it know that the "value" argument is a property with a setter or a plain field.
It is less clear for an event because there is so much syntax sugar at work. This declaration
public event EventHandler SomeEvent;
actually generates this code:
private EventHandler _SomeEvent;
public event SomeEvent {
add { _SomeEvent += new EventHandler(value); }
remove { _SomeEvent -= new EventHandler(value); }
}
The add and remove accessors are equivalent to the get and set accessors of a property, they prevent code from messing with the private _SomeEvent field. By convention, the add accessor is invoked when you use +=, remove is invoked with -=. Compare this with the earlier example I gave for a property. Same problem, you can't use the ref keyword and ClassC.addListener() would have no way to know that the handler is actually an event instead of a delegate object. If the compiler would pass _SomeEvent instead, the point of using the accessors is lost.
You can restructure the code to solve this problem:
class ClassC {
public EventHandler getListener() {
return new EventHandler(onEvent);
}
private void onEvent(object sender, EventArgs e) { }
}
...
a.SomeEvent += c.getListener();
One final note: the symmetry between an event and a property is a bit lost, the C# compiler automatically generates the add/remove accessors if you don't write them explicitly. It doesn't do this for a property. It would have made automatic properties a lot easier:
property int Property;
But that would have required adding a new keyword to the language, something the C# team really dislikes. Other languages like VB.NET and C++/CLI do have that keyword.
这篇关于在C#中为什么不能我通过其他类的事件处理程序的参考,我怎么能围绕它得到什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!