The FrameworkElement object has DataContextChanged event. However, there is no OnDataContextChanged method that can be overridden.
Any ideas why?
If a method is virtual, then the user has the option to either augment the base functionalty by calling the base class method or replace the base class functionality by failing to call the base class method. For OnEvent() methods, if you don't call the base class method then the event will not be raised (that's the responsibility of the base class method.) If the base class performs some kind of state management inside of the OnEvent method, this means that the derived class can accidentally invalidate the state of the object if the user chooses to omit a call to the base class method. Documentation can specify "please always call the base class method", but there's no way to enforce it.
When I see an event that doesn't have a virtual OnEvent() method, I usually assume the method performs some kind of internal state management and the designers of the class want to guarantee their state management runs. This isn't the case in FrameworkElement, and it's not the only event that doesn't follow the pattern, so I'm curious what the reasoning is.
I dug around in Reflector to see if I could discover a reason. There is an OnDataContextChanged() method, but it's a dependency property change handler and doesn't follow the standard event pattern. This is probably the reason for not making it protected virtual. It's non-standard, so it would be confusing. It's static, so you wouldn't be able to override it anyway. Since it's called automatically by the dependency property framework and you are unable to override it, I believe we have the reason why it's private instead of static virtual.
You could use a different pattern to expose the normal event pattern:
class FrameworkElement
{
// difference: use DataContextPropertyChanged as the change callback
public static readonly DependencyProperty DataContextProperty = ...
protected virtual void OnDataContextChanged(...)
{
// raise the DataContextChanged event
}
private static void DataContextPropertyChanged(...)
{
((FrameworkElement)d).OnDataContextChanged(...);
}
}
My guess why they didn't do this? Usually you call OnEvent() to raise the event. The event is automatically raised when DataContext changes, and it doesn't make sense for you to raise it at any other time.
Good question.
I'm just guessing, but looking in Reflector I'd say it's just laziness, perhaps with a pinch of (unfounded?) performance concerns. FrameworkElement has a generic EventHandlersStore which is responsible for maintaining event information (delegates) for a whole bunch of events. The add and remove logic in the CLR events (such as DataContextChanged) simple call into the EventHandlersStore with the appropriate key.
There is a generic RaiseDependencyPropertyChanged method that is called to raise all different sorts of events. There is also a private OnDataContextChanged method that calls the RaiseDependencyPropertyChanged method. However, it is static and registered as part of the d-prop metadata.
So, in short, I see no technical reason not to include an overridable OnDataContextChanged method. Just looks like a short-cut in implementation to me.
Is this merely academic, or are you trying to achieve something here?
Silverlight Note:
At of Silverlight Beta 4 there IS no DataContextChanged event (well its not public at least).
The Microsoft Connect bug report has been marked as 'Fixed' but with no indication of what that actually means.
In the meantime you need a workaround such as this one from CodeProject - which is very simple and should be easy to switch out if Microsoft ever actually makes the event public.
Dependency properties usually don't have corresponding virtual methods for raising the event because it's expected that the change events will be managed by the dependecy property system itself.
What you can override however, to handle any dependency property changing is DependencyObject.OnPropertyChanged like so:
class MyClass : FrameworkElement {
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) {
base.OnPropertyChanged(e);
if (e.Property == FrameworkElement.DataContextProperty) {
// do something with e.NewValue/e.OldValue
}
}
}
Related
I have been playing around with delegates, events, and anonymous methods. In doing so one point became very clear.
Would it not streamline the process of registering any event methods or delegate functions in the constructor?
My tests shows it works and it prevents you from having to declare them after instantiation (as the constructor of the object does it for you).
In fact, the performance is pretty good. Are there any drawbacks to using the "this" keyword to refer to the current object when constructing / instantiating the object?
This seems to make a lot of sense to me as all the events would be wired up on instantiation.
Are there any areas this might be an issue?
Example:
//Constructor
public SayHello()
{
_name = "Unnamed";
_isUpdated = false;
// Register event handler via lambda (ananymous method shorthand)
this.NameChanged += (object sender, EventArgs e) => { Console.WriteLine(e.message)); };
}
There are a couple of potential problems with this approach. First, on the more general side, one should usually favour using method overrides over subscribing to self-published events for performance reasons. Obviously, this isn't possible if the event is exposed by an externally sourced based class that exposes an event without a corresponding overridable method. However, subscribing to self-published events should be an approach of last resort, not a default approach.
The second potential problem is more serious, but it has to do with what the code triggered by the event does, not which object exposes the event. For example, consider the following constructor:
public Foo(Bar bar)
{
bar.SomeEvent += (s, e) => this.DoSomething();
}
If bar fires SomeEvent on another thread, your Foo instance's DoSomething method could be called before the instance has been fully initialized. This is a fairly well-documented problem in the Java space (see, for example, http://www.ibm.com/developerworks/java/library/j-jtp0618/index.html), but coverage is much sparser for C#/.NET. http://joeduffyblog.com/2010/06/27/on-partiallyconstructed-objects/ provides some detailed coverage for .NET, but it might be more than you wanted to know...
I don't think that there are any issues. It's up to you to do it in that way. You can use the object itself in its constructor. It would work too, if you omitt this.
I have Code OCD, so bear with me.
We have a base class with:
virtual protected void OnHierarchyInitialized()
{
}
Now when someone overrides this method, they almost are to be expected to call the base method:
protected override void OnHierarchyInitialized()
{
base.OnHierarchyInitialized();
}
But.. nothing is happening in the base method. Nor will in the future. I just don't want people that subclass need to 'worry' when and if they need to call the base method.
Plus: this is ugly fat in the implementing code, that distracts from the rest of the code that looks like a C# version of the Mona Lisa itself.
Of course I could make it an abstract method, but here is the big disadvantage that it needs to be implemented. Also screws up my work of art.
Question
Is there something in between a virtual and abstract method, that tells the message:
override me optionally, but there is no base method to call ?
Thanks in advance!
Pretty sure the only thing you can do is use the built in XML documentation to notify the callers. For example, this is how it would show up to the person overriding your method:
There is no keyword in c# to do that. virtual is the best there is for this approach.
Just don't worry about if there is an base class implementation or not. The one implementing the derived class shouldn't worry about it.
There is just one question: Does the current implementation totally replace the base class's implementation?
If it does, don't call the base class. If it doesn't: call it.
If your code looks like this:
public void Foo()
{
// do something
OnHierarchyInitialized();
// do something else
}
You may want to consider events instead of inheritance:
public event EventHandler HierarchyInitialized = delegate { };
OnHierarchyInitialized();
public void Foo()
{
// do something
OnHierarchyInitialized(new EventArgs());
// do something else
}
private void OnHierarchyInitialized(EventArgs e)
{
EventHandler handler = HierarchyInitialized;
handler(this, e);
}
Where consumers can then subscribe to the HierarchyInitialized event when they're interested in it.
If you're absolutely sure that the base method will never actually do anything, then an abstract method is exactly the right approach. I know you say this will screw up your work of art, but think about it like this: you want a way to explicitly tell the user that the base method does nothing. An abstract method will accomplish this, whilst reminding them that the method is there, even if they choose not to use it.
Think about how interfaces work - they are a collection of abstract methods that do nothing but have to be overridden. This is the correct approach, and compliments your work of art by enforcing the inclusion of the method. The empty method shows the user that they can hook into the OnHierarchyInitialized method to achieve something.
I have been playing around with delegates, events, and anonymous methods. In doing so one point became very clear.
Would it not streamline the process of registering any event methods or delegate functions in the constructor?
My tests shows it works and it prevents you from having to declare them after instantiation (as the constructor of the object does it for you).
In fact, the performance is pretty good. Are there any drawbacks to using the "this" keyword to refer to the current object when constructing / instantiating the object?
This seems to make a lot of sense to me as all the events would be wired up on instantiation.
Are there any areas this might be an issue?
Example:
//Constructor
public SayHello()
{
_name = "Unnamed";
_isUpdated = false;
// Register event handler via lambda (ananymous method shorthand)
this.NameChanged += (object sender, EventArgs e) => { Console.WriteLine(e.message)); };
}
There are a couple of potential problems with this approach. First, on the more general side, one should usually favour using method overrides over subscribing to self-published events for performance reasons. Obviously, this isn't possible if the event is exposed by an externally sourced based class that exposes an event without a corresponding overridable method. However, subscribing to self-published events should be an approach of last resort, not a default approach.
The second potential problem is more serious, but it has to do with what the code triggered by the event does, not which object exposes the event. For example, consider the following constructor:
public Foo(Bar bar)
{
bar.SomeEvent += (s, e) => this.DoSomething();
}
If bar fires SomeEvent on another thread, your Foo instance's DoSomething method could be called before the instance has been fully initialized. This is a fairly well-documented problem in the Java space (see, for example, http://www.ibm.com/developerworks/java/library/j-jtp0618/index.html), but coverage is much sparser for C#/.NET. http://joeduffyblog.com/2010/06/27/on-partiallyconstructed-objects/ provides some detailed coverage for .NET, but it might be more than you wanted to know...
I don't think that there are any issues. It's up to you to do it in that way. You can use the object itself in its constructor. It would work too, if you omitt this.
Say I have a class like this:
public class FauxIdentityForm
{
public Guid FormID { get; set; }
public event EventHandler Closed;
public void TheObjectWasClosed(EventArgs e)
{
Closed(this, e);
}
}
It is fine for me to call the Closed Event inside the TheObjectWasClosed method. But if, in a different class (even in the same file), I have a method like this:
public void CallTheEvent()
{
FauxIdentityForm _formIdentity = new FauxIdentityForm {FormID = Guid.NewGuid()};
_formIdentity.Closed(_formIdentity, null); // <-- Does not compile!
}
The call to Closed is shot down by the compiler (it wants me to only use += and -=).
So, is actually calling the event only allowed inside the class? Is that the limitation?
If so, is there anyway around it? And if not, why did the creators of C# do this? (It makes working with events very hard sometimes. I imagine there is a good reason and it is probably saving me from myself, but I would like to know it.)
It's complicated :)
What you're using is called a field-like event. When you declare one of those in your class, you're creating a field and an event. When you "call the event" you're actually invoking the delegate referred to by the field. As it's a private field, you have access to it within the class (and any nested types), but not outside.
Events themselves in C# only support add and remove operations. From the outside, callers can only subscribe to an event and unsubscribe from it. They can't raise it, or find out anything about who's subscribed. Of course, the class can provide a method which will raise the event, but the other class can't access the backing field for the event
I've written this up in more detail in an article about events and delegates.
In fact, Closed(this, e); is nothing but calling invoke on a private delegate. This is why only the class can call it.
C# hides all the complexity from you and it creates a private delegate of type event for you (you can use ILDASM to see all this).
This is private so it is not even protected. This is why it is recommended to use a protected method to raise the event so the subclasses could have access to the event.
So, is actually calling the event only allowed inside the class? Is that the limitation?
Yes
If so, is there anyway around it?
Only with the consent (help) from the FauxIdentityForm class. It could have a public OnClosed() method.
An Event is a lot like a property, one of its main purposes is encapsulation and that is what you ran into.
When designing a derived class, are there [dis]advantages to adding a handler to a base class event in the ctor vs overriding the OnEventName() method and adding some behaviour (as well as calling the base method), if one doesn't need to change the base method and doesn't care in what order things happen, but only wants a reusable component with a little extra behaviour?
base class:
public abstract class BaseClass
{
public event EventHandler SomeEvent;
protected void OnSomeEvent(object sender, EventArgs e)
{
// do some stuff
}
}
option A:
public class DerivedA
{
protected override void OnSomeEvent(object sender, EventArgs e)
{
// do some other stuff
base.OnSomeEvent(sender, e);
}
}
option B:
public class DerivedB
{
public DerivedB()
{
SomeEvent += (o,e) => { // do some other stuff };
}
}
There aren't any significant advantages/disadvantages to either approach.
There's a few differences between subscribing to an event vs. overriding a base-class method. For example, if you want some code to run before or after all other handlers, you should really override the OnSomeEvent method, as there's no way to gaurantee that otherwise. But you indicate you don't really care about this.
In general, overriding a method is something that requires a good understanding of the behavior of the base class to ensure that you don't inadvertantly break anything. Subscribing to an event is a less intrusive extensions, and is something that (presumably) the base class designer has planned for.
Sometimes, people argue that performance is better when overriding - but I don't buy this argument. Performance only matters when it matters. The difference here is likely so negligible, that one should be more concerned with simplicity, correctness, and easy of maintenance over performance.
You've already mentioned the order in which things are called. Some other things which admittedly don't happen all that often, but might be significant (based on the fact that the base class controls how the event handlers are invoked):
Event handlers might be called on a different thread;
Under some circumstances, the base class might choose not to call event handlers at all;
The base class might catch specific types of exceptions thrown by handlers; exceptions thrown by your handler might be unintentionally swallowed.
In general, I tend to see events as being there exclusively for a class's users, with a well-designed class having virtual On... methods for subclasses.