Virtual Override Events Inheritance

G

Guest

Hi
I use the following syntax to have events inherited from base to child classes which works nicely (virtual and override keyword on events). But I am wondering if it is a "supported" way of using events since I never saw it used anywhere in MSDN documentation/samples?! Or it will just break when I upgrade to .NET Framework 2.x in the coming years

namespace MyNamespac

public delegate void MyDel()

public class MyBase

public virtual event MyDel MyEvent
public void MyMethod2(

MyEvent()



public class MyDerived : MyBas

// Override base class event so that it can
// be raise from child (here!
public override event MyDel MyEvent

public void MyMethod(
{ // Raise event. Without the virtual/override keywords,
// child classes are not allowed to raise events declared
// in their base clas
MyEvent()




Thank
JPRoo
 
M

Mattias Sjögren

I use the following syntax to have events inherited from base to child
classes which works nicely (virtual and override keyword on events).
But I am wondering if it is a "supported" way of using events since I
never saw it used anywhere in MSDN documentation/samples?! Or it will
just break when I upgrade to .NET Framework 2.x in the coming years?

It's supported and documented alright. See

http://msdn.microsoft.com/library/en-us/csspec/html/vclrfcsharpspec_10_7.asp
http://msdn.microsoft.com/library/en-us/csspec/html/vclrfcsharpspec_10_7_4.asp



Mattias
 
J

Jerry Negrelli

I've never had the occasion to use that syntax, but the
ECMA C# spec says that virtual events should be supported
in the same way that virtual methods are, so I think
you're ok on that front. As to future support, does
anyone know where a 2.x spec might be that could change
that?

JER
-----Original Message-----
Hi,
I use the following syntax to have events inherited from
base to child classes which works nicely (virtual and
override keyword on events). But I am wondering if it is
a "supported" way of using events since I never saw it
used anywhere in MSDN documentation/samples?! Or it will
just break when I upgrade to .NET Framework 2.x in the
coming years?
 
A

Alvin Pruney

Do you mean the OnEventBlah method call which is defined as

protected virtual OnEvenetMethodHere(blah)
{
}

?
 
A

Alvin Pruney

Is the ECMA C# specs actually final or draft?

Has any other part submitted draft ammendments , after all surely anybody
could, right?
 
J

Jerry Negrelli

Here's a link to the most recent version of the spec:

http://www.ecma-
international.org/publications/standards/Ecma-334.htm

and everything's a work in progress, right? ;)

JER
 
1

100

Hi JPRoot,

IMHO this is indeed very strange way to use base class's events. And beside
I find it strange it is wrong or at least error prone.

You have to check the event for null before fire it because you can't know
if you have handlers registered for that event:
if(MyEvent != null) MyEvent();

But this is not the bigest flaw.

When you define an event as virtual actually you define its accessors (add
and remove) as virtual, but each class in the hierarchy will have its own
field of type *delegate void MyDel()* to hold the handlers

What does it means? Let me provide a new example.

public delegate void MyDel();

class Foo
{
public virtual MyDel MyEvent;
public FooRaiseMyEvent()
{
if(MyEvent != null) MyEvent();
}
}

class Bar: Foo
{
public override MyDel MyEvent;
public BarRaiseMyEvent()
{
if(MyEvent != null) MyEvent();
}
}

Now let we have the following code snippet

Foo foo = new Bar();
foo.MyEvent += new MyDel(foo_MyEvent);
Bar bar = (Bar) foo; //we can do that because the object is of type Bar.

bar.BarRaiseMyEvent(); //Everything is just perfect the event fires
bar.FooRaiseMyEvent(); // Bar inherits this method from Foo, but no event
fires.

Which means that no methods form the base class can fire the event. Imagine
if you have more classes in the hierarchy....

Why is this happen?
Because doing
foo.MyEvent += new MyDel(foo_MyEvent);
we call MeEvent's *add* accessor polymorphically and the one decalred in Bar
will be called. It will add the handler to the delegate chain in Bar's field
of type MyDel.
Now when BarRaiseMyEvent calles MyEvent() it uses Bar's delegate field,
which has something inside.
FooRaiseMyEvent., though, uses Foo's delegate field which has nothing inside
and no event is fired.
Access to Fields cannot be polymorphical.

To use events declared in the base class use the design pattern used
throughout the framework (OnXXX methods).
I believe it is described somewhere in MSDN but I don't remember where.
Try to look at
ms-help://MS.MSDNQTR.2003FEB.1033/cpguide/html/cpconprovidingeventfunctional
ity.htm


HTH
B\rgds
100

JPRoot said:
Hi,
I use the following syntax to have events inherited from base to child
classes which works nicely (virtual and override keyword on events). But I
am wondering if it is a "supported" way of using events since I never saw it
used anywhere in MSDN documentation/samples?! Or it will just break when I
upgrade to .NET Framework 2.x in the coming years?
 
G

Guest

That's a good new since having it documented makes it a little more difficult for MS to stop supporting it..

Second question then..
Seems by trial and error that the virtual keyword on the event "virtualize" only the Add and Remove accessor and not the Raise

Taking for exemple the code that I have posted previously, it appears that when raising the event in MyBase::MyMethod2() uses the invocation list of the base class instance MyBase::MyEvent and when raising the event MyDerived::MyMethod() it uses the invocation list of the derived class instance. That defeats the purpose of "virtual" where the base class doesn't use the specialized implementation?!

So if I register to the event, using a pointer to the base class or the child, it always get registered in the derived class invocation list (so Add/Remove are really virtual). If I call MyMethod I receive the event, if I call MyMethod2, I receive an exception stating that the event invocation list is empty !!

Any thoughts

Than
JPRoo


----- Mattias Sjögren wrote: ----

I use the following syntax to have events inherited from base to chil
classes which works nicely (virtual and override keyword on events)
But I am wondering if it is a "supported" way of using events since
never saw it used anywhere in MSDN documentation/samples?! Or it wil
just break when I upgrade to .NET Framework 2.x in the coming years

It's supported and documented alright. Se

http://msdn.microsoft.com/library/en-us/csspec/html/vclrfcsharpspec_10_7.as
http://msdn.microsoft.com/library/en-us/csspec/html/vclrfcsharpspec_10_7_4.as



Mattia
 
J

Jeffrey Tan[MSFT]

Hi,

I have reviewed your post. I will do some research for you.
I will reply to you ASAP.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Thread-Topic: Virtual Override Events Inheritance
| thread-index: AcOqNrWCuoOYF9SrS3WjsXs6rYhgEQ==
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| From: =?Utf-8?B?SlBSb290?= <[email protected]>
| References: <[email protected]>
<##[email protected]>
| Subject: Re: Virtual Override Events Inheritance
| Date: Thu, 13 Nov 2003 14:37:24 -0800
| Lines: 39
| Message-ID: <[email protected]>
| MIME-Version: 1.0
| Content-Type: text/plain;
| charset="Utf-8"
| Content-Transfer-Encoding: 8bit
| X-Newsreader: Microsoft CDO for Windows 2000
| Content-Class: urn:content-classes:message
| Importance: normal
| Priority: normal
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.0
| Newsgroups: microsoft.public.dotnet.languages.csharp
| NNTP-Posting-Host: TK2MSFTCMTY1 10.40.1.180
| Path: cpmsftngxa06.phx.gbl!cpmsftngxa10.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:199196
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| That's a good new since having it documented makes it a little more
difficult for MS to stop supporting it...

Second question then...
Seems by trial and error that the virtual keyword on the event "virtualize"
only the Add and Remove accessor and not the Raise.

Taking for exemple the code that I have posted previously, it appears that
when raising the event in MyBase::MyMethod2() uses the invocation list of
the base class instance MyBase::MyEvent and when raising the event
MyDerived::MyMethod() it uses the invocation list of the derived class
instance. That defeats the purpose of "virtual" where the base class
doesn't use the specialized implementation?!

So if I register to the event, using a pointer to the base class or the
child, it always get registered in the derived class invocation list (so
Add/Remove are really virtual). If I call MyMethod I receive the event, if
I call MyMethod2, I receive an exception stating that the event invocation
list is empty !!!

Any thoughts?

Thank
JPRoot



----- Mattias Sjögren wrote: -----

I use the following syntax to have events inherited from base to child
classes which works nicely (virtual and override keyword on events).
But I am wondering if it is a "supported" way of using events since I
never saw it used anywhere in MSDN documentation/samples?! Or it will
just break when I upgrade to .NET Framework 2.x in the coming years?

It's supported and documented alright. See


http://msdn.microsoft.com/library/en-us/csspec/html/vclrfcsharpspec_10_7.asp

http://msdn.microsoft.com/library/en-us/csspec/html/vclrfcsharpspec_10_7_4.a
sp



Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/
Please reply only to the newsgroup.

|
 
1

100

Hi JPRoot,
Ok, VC++ defines 3 accessors for events (for adding, removing and raising
the event).
*add* and *remove* accessors has the visibility which is specified for the
event when it is decalred. *Rise* accesor is almost always protected except
when the event is private then and *raise* accessor is private.

What does it mean?
That means that you don't have to do anything in C++ to inherit the base
event. So your code can be transformed to

namespace MyNamespace
{
public __delegate void MyDel();
public __gc class MyBase
{
public:
__event MyDel* MyEvent;

public:
void MyMethod2()
{
__raise MyEvent();
}
};

public __gc class MyDerived : public MyBase
{

public:
void MyMethod()
{
//This will raise the base class' event because raise_MyEvent
method is protected
__raise MyEvent();
}
};

public __gc class EventReceiver
{
public:
static void MyEventHandler()
{
System::Console::WriteLine("Event fired!");
}
};
};

int _tmain(void)
{
MyNamespace::MyDerived* aa = new MyNamespace::MyDerived();
MyNamespace::MyBase* bb = aa;
MyNamespace::MyDel* receiver = new MyNamespace::MyDel( 0,
MyNamespace::EventReceiver::MyEventHandler );
aa->MyEvent += receiver;
bb->MyEvent += receiver;
aa->MyMethod();
aa->MyMethod2();

MyNamespace::MyBase* cc = new MyNamespace::MyBase();
cc->MyEvent += receiver;
cc->MyMethod2();


System::Console::ReadLine();
return 0;
}

And this will work just perfectly.

This is not the case of C#, though. C# compiler doesn't generate *raise*
accessors for events and it inlines calls delegate's Invoke method whenever
it finds language constuction like DelegateMemberName(....).
For the sme line VC++ will generate call to raise_DelegateMemberName(....)
method.
Which means that VC++ programs cannot use classes written in C# because they
don't have raise_XXX methods defined as well as if you write the class
hierarchy as in the VC++ examples we discuss C# program will be able to use
the parent event only if the C# programmer knows about those raise_XXX
methods.

Who is wrong in this case. I'm really really confused.
If we look in CLI specification (Part I - Architecture) we can find:
Per 8.11.4 Event Definitions
The CTS supports events in precisely the same way that it supports
properties (see clause 8.11.3). The
conventional methods, however, are different and include means for
subscribing and unsubscribing to events as
well as for firing the event.

-------
C# doesn't generate method for *firing* the event.

Per 10.4 Naming Patterns
See also Partition V. 30
While the CTS does not dictate the naming of properties or events, the CLS
does specify a pattern to be
observed.
For Events:
An individual event is created by choosing or defining a delegate type that
is used to signal the event. Then,
three methods are created with names based on the name of the event and with
a fixed signature. For the
examples below we define an event named Click that uses a delegate type
named EventHandler.
EventAdd, used to add a handler for an event
Pattern: void add_<EventName> (<DelegateType> handler)
Example: void add_Click (EventHandler handler);
EventRemove, used to remove a handler for an event
Pattern: void remove_<EventName> (<DelegateType> handler)
Example: void remove_Click (EventHandler handler);
EventRaise, used to signal that an event has occurred
Pattern: void family raise_<EventName> (Event e)
------
C# creates only two names.
Per 8.10.3 Property and Event Inheritance
.....
The source compiler shall generate CIL that directly accesses the methods
named by the events and properties, not the events or properties themselves.

------
C# compiler doesn't use the method decalred for raising the event

And I finaly got lost in my confusion when I saw that no class of the
framework has raise_XXX method.

I have to confess that I haven't read the specs carefully so I might
misunderstood something.
Can anybody explain what CLI specification states and why only VC++
generates and uses *raise* methods?
Neither C# nor VB.NET do that

B\rgds
100



JPRoot said:
100,
You are 100% right.

The point I am trying to make is that the Add and Remove are made virtual
when you put the virtual keyword besides the event keyword but not the Raise
which I see as a bug(or lack of completeness of the feature) since in
VC++.NET Managed when you put the virtual keyword besides an __event not
only the Add and Remove becomes virtual but also the Raise method, which
makes complete sence!!
Other feature that C# lacks is a way to define the Raise method like you can do in VC++.NET Managed.

Here's the exact same snippet I first posted but in VC++.NET Managed where
event "virtualization" really works!! Also, having it this way, makes it
useless to have OnXXX pattern... or at least less useful :)
#using <mscorlib.dll>
#include <tchar.h>

using namespace System;

namespace MyNamespace
{
__delegate void MyDel();
public __gc class MyBase
{
public:
virtual __event MyDel* MyEvent;

public:
void MyMethod2()
{ // this should call child class event if overriden
__raise MyEvent();
}
};

public __gc class MyDerived : public MyBase
{
protected:
__event MyDel* m_myEventInvokeList;
public:
virtual __event void add_MyEvent(MyDel* d)
{
m_myEventInvokeList += d;
}

virtual __event void remove_MyEvent(MyDel* d)
{
m_myEventInvokeList -= d;
}

protected:
virtual __event void raise_MyEvent()
{
__raise m_myEventInvokeList();
}

public:

void MyMethod()
{ // Raise event. Without the virtual/override keywords,
// child classes are not allowed to raise events declared
// in their base class
__raise MyEvent();
}
};

public __gc class EventReceiver
{
public:
static void MyEventHandler()
{
System::Console::WriteLine("Event fired!");
}
};
};

int _tmain(void)
{
MyNamespace::MyDerived* aa = new MyNamespace::MyDerived();
MyNamespace::MyBase* bb = aa;
MyNamespace::MyDel* receiver = new MyNamespace::MyDel( 0,
MyNamespace::EventReceiver::MyEventHandler );
 
1

100

Hi JPRoot,
I made a post in other thread's branch. Anyway, I just want ot make a
comment here. C# doesn't use *raise* accessors. Which makes declaring an
event as virtual really really usless, except in the cases with event
declared as part of an interface. In the latter case event is abstract so
virtual. As I see you come from managed VC++ where to have virtual events
really make sense.

B\rgds
100

JPRoot said:
That's a good new since having it documented makes it a little more
difficult for MS to stop supporting it...
Second question then...
Seems by trial and error that the virtual keyword on the event
"virtualize" only the Add and Remove accessor and not the Raise.
Taking for exemple the code that I have posted previously, it appears that
when raising the event in MyBase::MyMethod2() uses the invocation list of
the base class instance MyBase::MyEvent and when raising the event
MyDerived::MyMethod() it uses the invocation list of the derived class
instance. That defeats the purpose of "virtual" where the base class doesn't
use the specialized implementation?!
So if I register to the event, using a pointer to the base class or the
child, it always get registered in the derived class invocation list (so
Add/Remove are really virtual). If I call MyMethod I receive the event, if I
call MyMethod2, I receive an exception stating that the event invocation
list is empty !!!
 
1

100

I don't know in general, but it works either ways for events. Anyway, even
if we use the sintax without __raise the compiler generates call to
raise_XXX method instead of direct call to delegate's Invoke methods as C#
and VB.NET do.

B\rgds
100
 
A

Alvin Bruney

Ignore this guy he is spoofing my email account. For credibility purposes I
suppose.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top