> I wrote a replacement for the native .NET class "FileDialog" with my own
> "FileOk" event (triggered when the user selects a file and clicks OK). Let's
[quoted text clipped - 8 lines]
> is ugly IMO however so I'm hoping there's a cleaner way. Any advice would be
> appreciated. Thanks.
If you don't want a client to be able to use a member of the base
class, you shouldn't derive from it.
You could make it virtual, override it, and add a deprecated attribute
to it - but it's a bit horrible. You *should* be able to use an
instance of a derived class as if it were an instance of the base
class.
Jon
MikeP - 27 Sep 2007 16:33 GMT
>> I wrote a replacement for the native .NET class "FileDialog" with my own
>> "FileOk" event (triggered when the user selects a file and clicks OK).
[quoted text clipped - 22 lines]
> instance of a derived class as if it were an instance of the base
> class.
Thanks for the feedback. Actually I agree with this in principle. However,
this was a very late change so I didn't want to have to start aggregating
the base class as a private member (as one possible solution), especially
for this one minor change. Note that in C++ you have more flexibility with
this issue. You can privately derive from a base class for instance and then
publicly expose only what you want. I find this approach somewhat ugly as
well however. In any case, I'll probably stick with my original idea until
the next release since I control all clients anyway (though I might add the
obsolete attribute you suggested). Anyway, thanks again.
Doug Semler - 27 Sep 2007 16:53 GMT
> You could make it virtual, override it, and add a deprecated attribute
> to it - but it's a bit horrible. You *should* be able to use an
> instance of a derived class as if it were an instance of the base
> class.
I *expect* to be able to use a derived class as if it were an instance
of the base class. :)
I have a feeling that the derived class event wants to pass more
information to the client than the base event. What I personally
would do is fire both events in the derived class. Let the client
decide which event to hook to, or even both (just document that both
events would be fired). I don't like this but it would be the
"easiest" solution...
Or you could virutalize the event, an OnEvent() method, and derive the
event args for the derived event from the base eventargs. Then the
client can hook to the same name (regardless). The derived class
fires the event with the derived event args, and the base class fires
the event with the base event args. It would be up to the client to
attempt to cast the base event args structure in the event handler to
determine what fired. I don't really like that either, it requires
the client to jump through some hoops in the event handler code....
The second case could look something like (IMO NOT "a good idea
(tm)"):
public class BaseEventArgs : EventArgs
{
public string BaseInfo
{
get
{
return "Only Base Info available";
}
}
}
public class DerivedEventArgs : BaseEventArgs
{
public string DerivedInfo
{
get
{
return "DerivedInfoAvailable";
}
}
}
public class BaseClass
{
virtual public event EventHandler<BaseEventArgs> MyEvent;
protected virtual void OnMyEvent()
{
EventHandler<BaseEventArgs> b = MyEvent;
if (b != null)
b(this, new BaseEventArgs());
}
internal void Fire()
{
OnMyEvent();
}
}
public class DerivedClass : BaseClass
{
public override event EventHandler<BaseEventArgs> MyEvent;
protected override void OnMyEvent()
{
EventHandler<BaseEventArgs> b = MyEvent;
if (b != null)
b(this, new DerivedEventArgs());
}
}
class Program
{
static void Main(string[] args)
{
BaseClass s = new DerivedClass();
s.MyEvent += new EventHandler<BaseEventArgs>(s_MyEvent);
Console.WriteLine("Firing Derived Class instance");
s.Fire();
s = new BaseClass();
s.MyEvent += new EventHandler<BaseEventArgs>(s_MyEvent);
Console.WriteLine("Firing Base Class instance");
s.Fire();
}
static void s_MyEvent(object sender, BaseEventArgs e)
{
DerivedEventArgs de = e as DerivedEventArgs;
if (de != null)
{
// Do stuff with derived event args
Console.WriteLine(de.DerivedInfo);
}
// Can do stuff with base event info
Console.WriteLine(e.BaseInfo);
}
}