There's really two questions here. First, what's with the add and remove in an event and second, what is an explicit interface implementation? These are orthogonal things.
Events with add and remove
In C#, events are actually a lot like properties. An event has an add
method and a remove
method. If you don't specify them explicitly, the compiler will create them for you as well as a delegate field to back the event (which you can access from within your own class by referring to the event).
You can create the add
and remove
methods yourself if you wish (and if you want to implement the interface explicitly, you must). In that case you usually also create a delegate field to back your event:
public event EventHandler SomeEvent
{
add { mSomeEvent += value; }
remove { mSomeEvent -= value; }
}
private void RaiseSomeEvent()
{
var handler = mSomeEvent;
if( handler != null ) handler( this, EventArgs.Empty );
}
private EventHandler mSomeEvent;
Notice that if you want to raise the event you have to refer to the backing field. You can no longer do it using the event name itself. You could actually do this for INotifyPropertyChange
without resorting to an explicit implementation.
Explicit Interface Implementation
When you implement an interface explicitly you actually create "private" versions of the interface members. Now, I put private in quotes because the implementation is not actually private. The implementation is only accessible if the cast is accessed from the interface type. That's a bit of a mouthful, so here's an example:
public interface IFoo
{
int Bar { get; }
}
public class A : IFoo
{
int IFoo.Bar
{
get { return -1; }
}
}
Now, let's say we have the following in a method somewhere:
var a = new A();
int bar = a.Bar;
This will generate a compile error, because the type A
doesn't have a publically visible member called Bar
. However, if we cast to IFoo
first:
var a = new A();
int bar = ((IFoo) a).Bar;
Now it compiles and when it runs, bar == -1
. You could also have strongly typed the variable a
as IFoo
as well:
IFoo a = new A();
int bar = a.Bar;
That would also work. So this member can be accessed from outside the class (and even outside the assembly), but only directly through the declaring interface type. This can be useful to hide implementation you don't want to support (like the mutable parts of IList<T>
) or if you have different implementations depending on the interface, like GetEnumerator()
in IEnumerable
as opposed to the GetEnumerator()
in IEnumerable<T>
.
public class B : IFoo
{
public int Bar { get { return 2; } }
int IFoo.Bar { get { return 1; } }
}
Now if we use this class like so:
B b = new B();
IFoo bAsIFoo = b;
int barFromB = b.Bar;
int barFromFoo = bAsIFoo.Bar;
What you'll get here is barFromB == 2
and barFromFoo == 1
.