problem in delegate declaration and its invocation - c#

When I try to call the event myevent in the function fire, it gives compiler error as
delegate mydelegate does not take 0 arguments.
if i try to give arguments in calling myevent as
myevent(this);
it again shows error as it does not take 1 parameters. what parameters am i supposed to give in the calling myevent? Here's the program code:
namespace useofdelegates
{
public class Class1
{ int i;
public delegate void mydelegate(object sender,EventArgs e);
public event mydelegate myevent;
public void fire()
{
myevent(this); // *** shows compiler error ***
}
}
}

The compiler error is because you are using a delegate with two parameters and calling it with one.
The simple solution is
myevent(this, EventArgs.Empty);
The more regular (and thread-safe) solution, which I think you're getting confused with is
OnMyEvent(EventArgs.Empty);
// and then later
public void OnMyEvent(EventArgs args)
{
mydelegate handler = myevent;
if(handler != null) handler(this, args);
}
The reason for doing it this way is that you should always make sure that there is at least one handler attached to the event. There is a small chance that the handler can be detached between checking for null and calling the handler, so it's good to pass it on to another variable which it cannot be detached from before checking for null.

You need to pass in 2 parameters. the first one being the source of the event. In your example "this" would work. The second one being of type EventArgs or a realted subclass. You can also pass EventArgs.Empty is you do not wish to pass any event especific information to the event handler.
So your method would look like this
fire(this, EventArgs.Empty);
or
fire(this, new MyCustomEVentArgs());
Here is an MSDN link with an example of using events http://msdn.microsoft.com/en-us/library/aa645739(VS.71).aspx
and nother one on creating custom EventArg subclasses to use in your handler. http://www.devarticles.com/c/a/C-Sharp/Creating-Custom-Delegates-and-Events-in-C-sharp/

You have declared mydelegate to require an object and an EventArgs, so you have to pass these in. Of course, you don't have declare your delegate with these arguments. You could just declare it thus:
public delegate void mydelegate();
or just pass this as the sender:
public delegate void mydelegate(object sender);

Just create an empty EventArgs I guess.
myevent(this, new EventArgs());
Note, here is the full code:
namespace useofdelegates
{
public class Class1
{
int i;
public delegate void mydelegate(object sender, EventArgs e);
public event mydelegate myevent;
public void fire()
{
myevent(this, new EventArgs()); // *** shows compiler error ***
}
}
}

Related

Why this delegate assignment does not work and how to solve it?

I have the following sample code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.del = this.EventHandler; <-- This does not build
}
public void EventHandler(object sender, PropertyChangedEventArgs e)
{
}
public delegate void A(object sender, EventArgs e);
private A del;
}
It complains about the delegate assignment. I suspect it is due to Covariance / Contravariance issues which honestly speaking is a concept that I do not fully understand.
Is there any way of making this code build? I need a generic handler for any event with any event args (inheriting from EventArgs).
Imagine, that this line is compiled:
this.del = this.EventHandler;
Then, here's a problem:
// since del must accept ANY EventArgs descendant, this should be possible:
del.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
// since del's signature IS (object, PropertyChangedEventArgs), we must convert
// NotifyCollectionChangedEventArgs to PropertyChangedEventArgs
// OOOPS...
I need a generic handler for any event with any event args
Use handler with this signature:
public void EventHandler(object sender, EventArgs e)
{
}
// compiles just fine
this.Loaded += EventHandler;
this.Closing += EventHandler;
this.Drop += EventHandler;
You can find an explication about delegate variance and covariance here
When you assign a method to a delegate, covariance and contravariance
provide flexibility for matching a delegate type with a method
signature. Covariance permits a method to have return type that is
more derived than that defined in the delegate. Contravariance permits
a method that has parameter types that are less derived than those in
the delegate type.
The method signature has to match with the delegate. If what you are trying to do would be allowed then you could pass any type to second parameter that inherits from EventArgs but it actually expects PropertyChangedEventArgs.
That can't work like that. In your example code, your EventHandler method requires e to be of type PropertyChangedEventArgs, i.e. a more specific type than what the delegate has declared.
It will work the other way around, i.e. your handler can be less specific than the delegate.
It should be
Use PropertyChangedEventArgs in A method Overloading
Because while Assigning Event to any delegate. their signature must be same
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.del = this.EventHandler; <-- This does not build
}
public void EventHandler(object sender, PropertyChangedEventArgs e)
{
}
public delegate void A(object sender, PropertyChangedEventArgs e);
private A del;
}

What are the differences between EventHandler and ElapsedEventHandler ?

So far in my limited use of c# I've subscribed to a couple of events.
Why do the following two code snippets use two diferent words EventHandler and ElapsedEventHandler?
myProcess = new Process();
myProcess.StartInfo.FileName = #"notepad.exe";
myProcess.Exited += new EventHandler(MyProcessExited);
compared to:
myTimer = new System.Timers.Timer(tickLength);
myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
are these words EventHandler and ElapsedEventHandler specific to the object whose event I'm using? Or are there a whole set of objects where I have to use "EventHandler" and different set of objects where I have to use "ElapsedEventHandler" ? (i.e for set X of objects we use xxxxxEventHandler etc)
Are these words EventHandler and ElapsedEventHandler specific to the
object whose event I'm using?
This words are names of delegates. And they are specific to information, which is passed from object, which raised event to subscribers of that event. Read about events, delegates and parameters passing below.
An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object. Events are declared using delegates.
So, if you want to notify client of some interesting thing happened in your object, you can declare delegate:
public delegate void SomethingHappenedDelegate();
And declare event of this type in your class:
class Foo
{
public event SomethingHappenedDelegate SomethingHappened;
// other code, which raises SomethingHappened event
// when something interesting happened
}
When clients of this class want to be notified that something interesting happenedthey should subscribe to SomethingHappened event. And event handler signature must match type of event (SomethingHappenedDelegate in this case):
static void Main(string[] args)
{
Foo foo = new Foo();
foo.SomethingHappened += new SomethingHappenedDelegate(Foo_SomethingHappened);
}
// this method should be: void MethodName()
static void Foo_SomethingHappened()
{
// you notified, that something happened
}
When you need to pass some additional data when notifying clients, you should use different delegate type, which takes some arguments. For example, if you want to pass some message to clients, change event's delegate type:
public delegate void SomethingHappenedDelegate(string message);
Now you should change event handler to correspond this delegate type:
static void Foo_SomethingHappened(string message)
{
// you notified, that something happened and you recieved a message
}
Another example, if we want to pass instance of object, which raised an event, and some additional arguments message and time:
public delegate void SomethingHappenedDelegate(object sender, string message, DateTime time);
Then we should have event handler with same signature:
static void Main(string[] args)
{
Foo foo1 = new Foo();
foo1.SomethingHappened += new SomethingHappenedDelegate(Foo_SomethingHappened);
Foo foo2 = new Foo();
foo2.SomethingHappened += new SomethingHappenedDelegate(Foo_SomethingHappened);
}
// we use same event handler for all SomethingHappened events
static void Foo_SomethingHappened(object sender, string message, DateTime time)
{
Foo foo = sender as Foo; // now we get object, which raised event
// and we can use message and time
}
So, all events have type of some delegate. Definition of that delegate describes which parameters should receive method, which will be handling event. In your code you use two events - Process.Exited and Timer.Elapsed. Lets look how these events defined:
public event EventHandler Exited;
public event ElapsedEventHandler Elapsed;
You can see here different types of delegates:
public delegate void EventHandler(object sender, EventArgs e);
public delegate void ElapsedEventHandler(object sender, ElapsedEventArgs e);
As you can see from definition, these delegates have same first parameter (sender), and different last parameter. So, handlers of these events also should have different signature, which should match these delegates.
You may wonder, why name of second parameter ends with EventArgs. If you want to notify other objects, that SomethingHappened, then following convention exists in C#:
event name should be SomethingHappened
if clients need some additional data to be passed, these data encapsulated in object, which derives from EventArgs class: SomethingHappenedEventArgs.
event delegate should be EventHandler (if no additional info should be passed to clients), or it should be of generic type EventHandler<SomethingHappenedEventArgs>, or it should be custom delegate with name SomethingHappenedEventHandler and signature void (object sender, SomethingHappenedEventArgs e)
Read more here.
No, the event names are matter of framework designer choice + they are toughly coupled to delegates that rapresent the event of any specific object.
EventHandler defininton is:
[Serializable]
[ComVisible(true)]
public delegate void EventHandler(object sender, EventArgs e);
ElapsedEventHandler definiton is:
public delegate void ElapsedEventHandler(object sender, ElapsedEventArgs e);
As you can see they are different delegate types.

Getting the target of an anonymous method

The following methods are part of a base class which enables derived classes to specify who should be notified by an event.
protected void RaiseEvent<TEventArgs>(EventHandler<TEventArgs> updateEvent, TEventArgs eventArgs, UpdateReceivers updateReceivers)
where TEventArgs : EventArgs
{
EventHandler<TEventArgs> handler = updateEvent;
if (handler != null)
{
if (updateReceivers.ToAllSubscribers)
{
handler(this, eventArgs);
}
else
{
NotifySpecifiedReceiver(handler, eventArgs, updateReceivers.Receiver);
}
}
}
private void NotifySpecifiedReceiver<TEventArgs>(EventHandler<TEventArgs> handler, TEventArgs eventArgs, object updateReceiver)
where TEventArgs : EventArgs
{
foreach (Delegate #delegate in handler.GetInvocationList())
{
// is the delegates target our receiver?
// but this doesnt work for anonymous methods :(
if (#delegate.Target == updateReceiver)
{
try
{
#delegate.DynamicInvoke(this, eventArgs);
}
catch (Exception ex)
{
}
}
}
}
To notify only a specific receiver, the method is used like this: (the receiver has to be subscribed of course)
event EventHandler<SomethingChangedEventArgs> SomethingChanged;
RaiseEvent(SomethingChanged, args, UpdateReceivers.Single(receiver));
This will only raise the delegates "pointing" to the receiver.
My problem here is when i use a anonymous method to subscribe to the SomethingChanged event its doesnt work when i use this event to notify the object which subscribed to it.
class EventConsumer
{
private EventSource _eventSource;
private void SubscribeEvents()
{
// ReactOnEvent() will not be called because the check [#delegate.Target == updateReceiver] doesnt work for anonymous methods
_eventSource.MyStateChanged += (sender, e) => ReactOnEvent();
_eventSource.PublishCurrentState(this);
}
}
class EventSource
{
// multiple objects are subscribed to this event
event EventHandler<MyStateChangedEventArgs> MyStateChanged;
public void GetCurrentState(object receiver)
{
// receiver ask for the current state, only raise event for him
RaiseEvent(MyStateChanged, args, UpdateReceivers.Single(receiver));
}
}
Is it possible the get the instance containing a anonymous method? or should i use a complete different approach to solve my problem?
You're (presumably) seeing the compiler-generated closure class that contains variables used by the anonymous method.
This class has specifically-named fields that reference information from the parent class.
You can use reflection to find a field in the compiler-generated DisplayClass (the Target value) named <>4__this, and get its value to find the instance of the class that created the delegate.
However, don't do this.
This relies on an internal behavior of the C# compiler that may change at any time.
Also, the fields contained by the closure class depend on where the anonymous method is and what members it references. If the anonymous method doesn't use the class instance, it may not have a this field at all.

public event EventHandler SomeEvent = delegate { };

I am kind of tired of having all this useless noise in my code:
private void RaiseSomeOtherEventIfItIsNotNull()
{
if (this.SomeOtherEvent != null)
{
this.SomeOtherEvent(this, EventArgs.Empty);
}
}
In 99.9% of the cases I don't care if someone attached to it or if it is null or not. Just raise the event! I really don't get it why the c# compiler makes me write all this noise.
So I though I could maybe declare an event like this:
public event EventHandler SomeOtherEvent = delegate { };
this would allow me to get rid of the useless null check and the useless Raise* Method. I could just always do:
this.SomeOtherEvent(this, EventArgs.Empty);
Now when I compare the standard approach with "my" approach in Lutz Röder's Reflector I see some signigicant differences. The compiler has overriden Add{} and Remove{}there is an extra static instance of the anonymous delegate:
[CompilerGenerated]
private static EventHandler CS$<>9__CachedAnonymousMethodDelegate1;
and there is this:
.method private hidebysig static void <.ctor>b__0(object, class [mscorlib]System.EventArgs) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
.maxstack 8
L_0000: nop
L_0001: ret
}
Now my question: Do you seen any issues or disadvantages in decalring events with a default initialization like this?
You've shown an extra method, but not the extra class. The extra method is fine, IMO - that's just representing the no-op handler. Not a problem.
An extra class is somewhat surprising, as is the idea that it's changing the add/remove behaviour... the compiler would always be creating add/remove methods for the event, as that's what makes it an event.
Personally I think this is fine - but an alternative would be to write extension methods, e.g.
public static void Raise<T>(this EventHandler<T> handler, object sender, T args)
where T : EventArgs
{
if (handler != null)
{
handler(sender, args);
}
}
public static void Raise(this EventHandler handler, object sender,
EventArgs args)
{
if (handler != null)
{
handler(sender, args);
}
}
then just call
myEvent.Raise(this, args);
That will work for all EventHandler and EventHandler<T> events.
The convention used by microsoft is this :
Declare the event like this.
public event EventHandler<ChangedArgs> ItemChanged;
Then create a calling method
protected virtual void OnItemChanged(ChangedArgs args)
{
var handler = ItemChanged;
if (handler != null)
handler(this, args);
}
This also is ThreadSafe and whenever to raise the event, simply call OnItemChanged
As far as I can tell, no, since these are no-op handlers (since the IL generates a nop and a ret instruction). Assigning an empty handler is pretty much the same as having none at all, i.e. you do nothing about that event.
I could be completely wrong (and if so, do tell me why, I'm curious too now), but maybe you need to declare the event delegate at class level?
public delegate void SomeEvent(object sender, EventArgs e);
?

C# Delegates and method signatures

From MSDN:
Any method that matches the delegate's
signature, which consists of the
return type and parameters, can be
assigned to the delegate.
So how is this possible:
public delegate void AlarmEventHandler(object sender, EventArgs e);
public event AlarmEventHandler Alarm;
protected virtual void OnAlarm(EventArgs e)
{
AlarmEventHandler handler = Alarm;
if (handler != null)
{
// Invokes the delegates.
handler(this, e);
}
}
delegate AlarmEventHander and event AlarmEventHandler have different signatures yet handler can be assigned to Alarm.
Perhaps I'm mis-understanding delegates somewhat, and I would be very grateful if someone could explain where I'm going wrong.
A delegate is like a class. An event is like a property. When you declare an event in a class, you declare the type of event it is. In this case, AlarmEventHandler, which is an inner class of the top-level class this is a part of.
In the OnAlarm method, you get the instance of the AlarmEventHandler class that has been assigned to the event, and invoke it.
To clear things up, your code above is similar to this, using normal classes & references:
public class InnerClass {
public void MyMethod() { /* ... */ }
}
public InnerClass MyProperty { get; set; }
protected virtual void CallMyMethod() {
InnerClass cls = MyProperty;
if (cls != null)
cls.MyMethod();
}
Actually the signatures are the same. In .NET events are implemented with delegates.
public event AlarmEventHandler Alarm;
So above code is actually compiled by compiler as:
private AlarmEventHandler handler;
public event AlarmEventHandler Alarm
{
add { handler += value; }
remove { handler -= value; }
}
So event actually uses the same AlarmEventHandler delegate.
You are mixing delegates and events. While events are dependant on delegates, they are difference concepts completly. So should be taken separately.
Delegate is like type definition. Place where you use this delegate is like variable or property.
Event makes this delegate behave differently from the outside. Signature is still same.
An event is just a delegate. The delegate itselft can only be accessed from inside the class.
From the outside, only add and remove functionality for the event is possible to you can only do this:
myAlarm.Alarm+=new AlarmEventHandler(callPolice);
// or
myAlarm.Alarm-=new AlarmEventHandler(callPolice);
But from the inside of the class, Alarm is just a delegate of type AlarmEventHandler so you can do what your code shows:
AlarmEventHandler handler = Alarm;
if (handler != null)
{
// Invokes the delegates.
handler(this, e);
}
A function which takes a base-class as (non reference) parameter can be converted to a delegate that takes a derived class as parameter. This is because the function that takes base can be safely substituted where-ever a function that takes a derived class is used.
void TakesObject(object o)
{
...
}
Action<string> myAction=TakesObject;
You can call myAction only by passing in a string. And since every string is an object the contract for TakesObject is fulfilled.
In your case is works because every AlarmEventArgs is an EventArgs too. So the contract requirements of your eventhandler are less strict than the contract guarantees of the delegate type used by the event.
This is called co- and contra-variance. You have co-variance in return-types, and contra variance in parameters.
Check this article on MSDN:
Using Variance in Delegates (C# and Visual Basic)

Categories