There are many questions about events in interfaces. Here are a couple:
Raising events in Interfaces
C# - Events and Interfaces
As interfaces are used to enforce a contract for implementation, this makes no sense to me, because it doesn't enforce the actual raising of the event. The specific implementation can always have the event, but not raise it anywhere. Consider the following:
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
public class SomeClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string SomeProperty
{
get { return this.someField; }
set { this.someField = value; }
}
private string someField;
}
The thing above will compile and work, but even if I subscribe to the PropertyChanged event, nothing will happen. What would be a way to enforce that an event is actually raised, and if not, why have events in interfaces in the first place?
The interface contract defines that the event must be implemented, and may be subscribed to. Actually raising it is left up to the concrete implementation. There is no way to enforce that an event is raised. What if the circumstances required to trigger the event never occur?
You misunderstood the concept of an interface: It explicitely declares an object's behaviour, but it does not enforce it in any way. The programmer is still fully responsible for implementing the interface behaviour correctly. This is nothing a compiler could do.
It's the same as with other contracts, when the involved parties just refuse to adhere to its content...
Thomas
The same can be said for methods: the interface doesn't enforce that they do anything useful, they could all just return null/0/void. Similarly, the implementation is free to raise/not raise an eevent whenever it wants.
If you want to ensure that certain behaviors are executed, then implement them as a abstract base class. Make the public methods public and non-virtual, and then have them call virtual protected methods and raise events. This is the template-method pattern, and it lets you have more control over sub-class behavior.
Another situation in which PropertyChanged will never be raised is the circumstance that the property is never changed! Do you want to be warned about that too?
But seriously, interfaces are for enforcing a contract of supported behaviour - if you want to enforce actual behaviour (ie - IF this happens THEN that happens), use (automated) testing.
Integration tests or unit tests are the only way that I see you could do what you want. You are then making sure in your implementation the behaviour is what you expect.
Nothing's really enforced in an interface, you can just put empty method stubs in after all (as long as you return something of the correct type).
The best way to ensure things like this are behaving correctly is to have plenty of tests.
One thing you might consider is code contracts, which let you specify conditions which have to be true at certain times, and these are actually enforced. However, AFAIK this doesn't work with events.
My take is that this provides a means of subscribing to an event when all you have reference to is the interface an object is using. Otherwise you would not be able to subscribe to the event at all. You are correct that it does not guarantee that the event is used.
INotifyPropertyChanged x = new SomeClass();
x.PropertyChanged += MyHandler; //you get the idea
If the event were not defined on INotifyPropertyChanged you would not be able to add your handler.
Related
Interview question: Why can't events be invoked and their invocation list set from outside of the declaring class?
I found explanation to the first part of the question in this post Events Invocation
I assume the answer for the second part lies with security.
Are there any other reasons considerations?
A keyword your interviewer may be looking for is encapsulation.
Events are only supposed to expose subscribe and unsubscribe operations to potential subscribers. Invocation is really the responsibility of the class that exposes the event.
Also keep in mind that public event EventHandler FooBar; is a short form of the following syntax
private EventHandler _fooBar;
public event EventHandler FooBar
{
add
{
_fooBar = (EventHandler)Delegate.Combine(_fooBar, value);
}
remove
{
_fooBar = (EventHandler)Delegate.Remove(_fooBar, value);
}
}
See Event Accessors
Because the class is the owner of those events.
We say that example in OOPS should be taken from real world examples. So if you are an entity and you do an event of let's say raising your hand, would you like to keep the authority of raising your hand with yourself or give to someone else?
But there is a catch
A C# short-format event declaration direct the compiler to declare a field of delegate type which, for unfortunate historical reasons, is given the same name as the event. Because the field declaration is generated by the compiler, rather than being part of user code, there is no means by which its scope can be set to anything other than private. If you wish to have the delegate or delegates associated with an event be accessible to child classes, then it's necessary to use something like the form shown by Brandon Cuff (though perhaps guarded with an Interlocked.CompareExchange).
I have a class that implements INotifyPropertyChanged and also has its own concept of properties, a little bit like this:
class sealed MyClass : INotifyPropertyChanged
{
private Dictionary<string, object> _properties;
public object GetProperty(string name)
{
return _properties[name];
}
public object SomeProperty
{
get
{
return GetProperty("SomeProperty");
}
}
}
Note that some common properties also have C# accessors.
I want to raise an event to notify others that a property (whose value is accessed through the GetProperty method) has changed even if this property does not have a corresponding C# accessor.
Assuming that there is no risk of a clash (i.e. inadvertantly raising a property changed event for a C# property whose value has not changed - note that this class is sealed), is there any reason why I can't just use the INotifyPropertyChanged.PropertyChanged event to notify others, or should I add my own event for this purpose?
I would suggest that you add your own. Although there's no specific reason that the code would break, INotifyPropertyChanged has a specific intended usage, and one that is understood by a lot of potential consumers. I'd not personally write code that contradicts that, just in case.
As far as I know, there's no harm in raising PropertyChanged for a property that isn't there, but I don't think it's very useful either. INotifyPropertyChanged is mostly used by data binding systems (in WinForms, WPF, Silverlight...), and these system don't know how to access your custom "properties".
Now, what you could do is implement ICustomTypeDescriptor to provide access to your custom properties in a standard way. This works with Windows Forms and WPF, I'm not sure about other frameworks.
Of course, if your intention is not to use this for data binding, you can still use this event to notify consumers of your class that values have changed.
Technically, it depends on who has subscribed to PropertyChanged and what they do in response to the PropertyChanged event. If they don't try to read a .NET "property", you're fine.
But, that really introduces a coupling and the use of INPC is trying to decouple. INPC at the general case assumes PropertyChanged means a .NET property (of a given name) has changed and is expected to be the case for all places that use INPC. i.e. you implement INPC because you want to use your object in any place that accepts INPC. If your object can't do that, then it violates the implied contract of INPC. If you have a PropertyChanged handler that does something different than read a property and you're re-using INPC just because it's there then maybe writing you own interface is a good idea.
In C# in depth (an excellent book thus far), Skeet explains events aren't fields. I read this section many times and I don't understand why the distinction makes any difference.
I am one of those developers that confuse events and delegate instances. In my mind, they are the same. Aren't both just a form of indirection? We can multicast both. An event is setup as a field as shorthand...sure. But, we are adding or removing handlers. Stacking them up to be called when the event fires. Don't we do the same thing with delegates, stack them up and call invoke?
The other answers are basically correct, but here's another way to look at it:
I am one of those developers that confuse events and delegate instances. In my mind, they are the same.
An old saying about not seeing the forest for the trees comes to mind. The distinction that I make is that events are at a higher "semantic level" than a field of delegate instance. An event tells the consumer of the type "hi there, I am a type that likes to tell you when something happens". The type sources an event; that's part of its public contract.
How, as an implementation detail, that class chooses to keep track of who is interested in listening to that event, and what and when to tell the subscribers that the event is happening, is the business of the class. It happens to typically do so with a multicast delegate, but that's an implementation detail. It is such a common implementation detail that it is reasonable to confuse the two, but we really do have two different things: a public surface, and a private implementation detail.
Similarly, properties describe the semantics of an object: a customer has a name, so a Customer class has a Name property. You might say that "their name" is a property of a customer, but you would never say that "their name" is a field of a customer; that's an implementation detail of a particular class, not a fact about the business semantics. That a property is typically implemented as a field is a private detail of the class mechanics.
Properties aren't fields either, although they feel like them. They are actually a pair of methods (getter and setter) with special syntax.
Events are similarly a pair of methods (subscribe and unsubscribe) with special syntax.
In both cases, you usually have a private "backing field" inside your class, which holds the value manipulated by the getter/setter/subscribe/unsubscribe methods. And there's an auto-implemented syntax for both properties and events where the compiler generates the backing field and accessor methods for you.
The purpose is also the same: Properties provide restricted access to a field, where some validation logic is run before storing a new value. And an event provides restricted access to a delegate field, where consumers can only subscribe or unsubscribe, not read the list of subscribers, nor replace the whole list at once.
Let's consider the two ways to declare events.
Either you declare an event using an explicit add/remove method, or you declare an event without such methods.
In other words, you declare the event like this:
public event EventHandlerType EventName
{
add
{
// some code here
}
remove
{
// some code here
}
}
or you declare it like this:
public event EventHandlerType EventName;
The thing is, in some ways they're the same thing, and in other ways, they're completely different.
From the perspective of outside code, that is ... code outside of the class publishing the event, they're the exact same thing. To subscribe to an event, you call a method. To unsubscribe, you call a different method.
The difference is that in the second example code above, those methods will be provided by the compiler for you, however, that's still how it's going to be. To subscribe to the event, you call a method.
The syntax to do so, in C#, however, is the same, you do either:
objectInstance.EventName += ...;
or:
objectInstance.EventName -= ...;
So from the "outside perspective", the two ways are no different at all.
However, inside the class, there is a difference.
If you try to access the EventNameidentifier inside the class, you're actually referring to the field that backs the property, but only if you use the syntax that doesn't explicitly declare an add/remove method.
A typical pattern is like this:
public event EventHandlerType EventName;
protected void OnEventName()
{
var evt = EventName;
if (evt != null)
evt(this, EventArgs.Empty);
}
In this case, when you're referring to EventName, you're actually referring to the field that holds the delegate of type EventHandlerType.
However, if you've explicitly declared the add/remove methods, referring to the EventName identifier inside the class will be just like outside of the class, since the compiler cannot guarantee that it knows the field, or any other mechanism, in which you store the subscription.
An event is an accessor for a delegate. Just like a property is an accessor for a field. With the exact same utility, it prevents code from messing with the delegate object. Like a property has a get and set accessor, an event has the add and remove accessor.
It does behave somewhat different from a property, if you don't write the add and remove accessors yourself then the compiler auto-generates them. Including a private backing field that stores the delegate object. Similar to an automatic property.
You don't do this often but it is certainly not unusual. The .NET framework pretty commonly does so, for example the events of the Winforms controls are stored in an EventHandlerList and the add/remove accessors manipulate that list through its AddHandler() and RemoveHandler() methods. With the advantage that all the events (there are many) require only a single field in the class.
I can add to the former answers that delegates can be declared inside a namespace scope (outside a class) and events can be declared only inside a class.
This is because delegate is a class!
Another distinction is that , for events, the containing class is the only one that can fire it.
You can subscribe/unsubscribe to it via the containing class, but can't fire it (in contrast to delegates).
So maybe you can understand now why the convention is to wrap it inside a protected virtual OnSomething(object sender, EventArgs e). It is for the descendants to be able to override the implementation of the firing.
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
}
}
}
I want to subclass ObservableCollection to add a property to it. Unfortunately, the PropertyChanged event is protected. Basically, I want to subclass it to have a SelectedItem that I can bind to for lists in my MVVM WPF app.
Here's the skeleton of my class:
public class SelectableList<T> : ObservableCollection<T>
{
public T SelectedItem {get;set;}
}
But I cannot do the following:
SelectableList<int> intList = new SelectableList<int>();
intList.PropertyChanged += new PropertyChangedEventHandler(intList_Changed);
because of access restrictions. This causes me to ask a deeper question. How is the UI notified of PropertyChanged events (e.g. Count property)? Note that I cannot do it in a code-behind.
My head is spinning, can someone please enlighten me?
SelectableList<int> intList = new SelectableList<int>();
((INotifyPropertyChanged)intList).PropertyChanged +=
new PropertyChangedEventHandler(intList_Changed);
ObservableCollection implements INotifyPropertyChanged explicitly, which means you have to cast the instance to the interface before you can access the interface's methods, properties and events. As to why this is done, I don't know. The Binding markup extension doesn't "know" ObservableCollections or any other type. It checks types to see if they implement or extend specific interfaces/base classes (INPC, INCC, DependencyObject, etc) and so doesn't care if the interface is implemented explicitly.
ObservableCollection (int .NET 3.5) appears to implement the PropertyChanged event in an interesting way.
protected event PropertyChangedEventHandler PropertyChanged;
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;
This means that the protected PropertyChanged event is likely only meant to be used for internal implementation. The other INotifyPropertyChanged.PropertyChanged event is the one that actually fulfills the implementation of the INotifyPropertyChanged interface as an explicit interface. Strangely I do not see any place within the ObservableCollection where the INotifyPropertyChanged.PropertyChanged is actually raised. This may signal that this was a bug in .NET 3.5 although I haven't tested to confirm whether for example a property changed event is raised for Count when an item is added to a collection but that appears to be how it is supposed to work.
In the .NET 4.0 implementation it appears that the INotifyPropertyChanged.PropertyChanged event instead hooks to the same private delegate used by the protected PropertyChanged event which may have been a bug fix. It is also possible this is just due to differences in how auto event implementations are handled in .NET 4.0.
Correction: I have verified that the INotifyPropertyChanged.PropertyChanged event is raised by ObservableCollection so the assumptions I made above based on results from using Reflector to look at the ObservableCollection implementation must be inaccurate. My guess is that reflector is doing something strange bug I have no proof of that yet.
So to get your example to work you would need to write for this to work would look like the example below just as Will has demonstrated in his answer.
SelectableList<int> intList = new SelectableList<int>();
((INotifyPropertyChanged)intList).PropertyChanged +=
new PropertyChangedEventHandler(intList_Changed);
Interesting right? Using explicit interfaces is mainly used to avoid inevitable collisions in members required for a given interface but they can be used to in a sense hide the existence of a member.
If you would like to raise property change events for your own custom properties that you introduce in your subclass look into overriding and/or calling the protected OnPropertyChanged method that ObservableCollection also implements. This technique is a well adopted standard and allows subclasses to raise events or handle events without having access to the underlying event delegate. It is generally preferred to use this technique too by the way instead of having a subclass hook event handlers to it's own base classes events. For more examples look at how events in various controls are implemented in WinForms and WPF.
I tried to add a new property in
public class ResultCollection<T> : ObservableCollection<T>
{
Boolean _val;
public Boolean Val
{
get
{
return _val;
}
set
{
_val= value;
OnPropertyChanged(new PropertyChangedEventArgs("Val"));
}
}
}
I really didn't notice that PropertyChanged is defined as protected. Finally moved Val property to ViewModel.
The UI can and does get notified. This is a restriction JUST with ObservableCollection, which defines the PropertyChanged event as protected.
FWIW, I think you're better off leaving ObservableCollection alone and just adding another property to your VM.