Jeffrey Tan MSFT forget me? Virtual Override Events Inheritance

G

Guest

Hi M. Jeffrey Tan,

Just hopping you didn't forget me? :)

Thanks
JPRoot

----- \"Jeffrey Tan[MSFT]\" wrote: -----


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.
----- JPRoot wrote: -----

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 );
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;
}

--------------------
| 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.

|
 
J

Jeffrey Tan[MSFT]

Hi,

Sorry, it seems that I missed the original thread. Let's continue in this
thread.

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.
 
J

Jeffrey Tan[MSFT]

Hi,

Oh, as I see in original post, 100 at last has posted a reply to you.
Does that make sense to you?

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.
 
J

JPRoot

100 explained the difference between C++ and C#, and yes the explaination
make a lot of sense to explain the current behavior. But it also means that
the virtual/override keyword in C# on an event is useless since the raise
method is not made virtual, like it is supposed to like the Add and Remove.

It so much make sense in C++.NET Managed that I cannot beleive that it was
made by design this way in C#.

I would like to ear from you (a Microsoft representative) if it is by
design(A) or if it is a bug(B)?

....I strongly hope it is a bug! ...so that it will be corrected :) ...

Thanks a lot!
JPRoot

PS: I don't know where we can post suggestions but I would like very much to
see in next version of C# to have a way to implement the Raise method like
we can do in C++.NET Managed.
 
J

Jeffrey Tan[MSFT]

Hi,

Sorry for letting you waiting for so long time.
I do not feel well these days and leave for sick yesterday. Ok, forget it,
let's work on your issue.

For your issue, I think it is an interesting problem, I have reproduced
your problem.
I will spend more time on this to find if this is by design. I do as soon
as I can.
Thanks for your understanding.

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.
 
J

Jeffrey Tan[MSFT]

Hi,

I still did not find a solid explanation for this issue, I will go and find
someone else to help you on this.
Thanks for your understanding.

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.
 
J

Jeffrey Tan[MSFT]

Hi,

This is by design in the C# language though not really a CLS issue though.

The reference to MyEvent in the base class refers (non-virtually) to the
compiler generated backing store for the event. While the client of the
event connected to the event through a virtual call to the derived add
accessor via the += operator. The real issue is that in the derived class
there is two backing stores for the event, one in the base class, one in
the derived class. Declaring an override event with the field syntax
(rather than the property syntax) is in general not what you want to do.
Either the base event should be abstract, or (more likely) the override
event should be declared with the property syntax, and defer storage (and
the method which raises the event) to the base class. Something like:

class Class1
{
public delegate void MyDel();
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
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.FooRaiseMyEvent();
Console.Read();
}

class Foo
{
public virtual event MyDel MyEvent;
public void FooRaiseMyEvent()
{
if(MyEvent != null)
{
Console.WriteLine("FooRaiseMyEvent");
MyEvent();
}
}
}

class Bar: Foo
{
public override event MyDel MyEvent
{
add
{
base.MyEvent += value;
}
remove
{
base.MyEvent -= value;
}
}
}

public static void foo_MyEvent()
{
Console.WriteLine("get called");
}
}

If you still feel it uncomfortable, you can provide your suggest to :
http://register.microsoft.com/mswish/suggestion.asp or mail to
(e-mail address removed)

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.
 

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