I need to start a download of some html so I call void GetHTML in another class. When it's done I want to pass along what Event it should raise in the calling class. How could I do this?
So it would look something like this:
public class Stuff
{
public void GetHTML(string url, event to raise here)
{
//Do stuff then raise event
}
}
public class Other
{
public Other()
{
Stuff stuff = new Stuff();
stuff.GetHTML(someUrl, somehow sending info that HTML_Done should be called);
}
void HTML_Done(string result, Event e)
{
//Do stuff with the result since it's done
}
}
I realize I'm not super clear with what I want to do, I'd be glad to fill in any missing parts.
Thanks for any suggestions!
You want a callback.
If you want to pass arguments, define the Action appropriately, ie;
Action<string>
, and then the callback becomescallback("some string")
The other option you have, is by using Events. It looks like that was what you were aiming for when you asked the question. I wouldn't recommend it, the callback option is nicer IMO. Though, for future reference, this is how you'd use an Event in this circumstance.
Info on how to use Events in C#.
Using this pattern allows many more subscribers.
You also do not tie the notifier, the
Stuff
class, to the caller, theOther
class.You either have subscribers or not, no difference to the
Stuff
class.The
Stuff
class should not know about the subscriber, it should merely raise an event it exposes for subscription.EDIT
As ctacke pointed out correctly in the comments, raising the event using
this.GetHtmlDone(this, new EventArgs());
will cause an exception if nobody has subscribed.I changed my code above to ensure the event can be raised safely at all times by initialising my eventhandler.
As I'm always using it (by raising it) I'm sure it is only good practise to always initialise what you are using.
I could have added a null check on the event handler but in my personal oppinion I do not agree with that having to be the responsibility of the
stuff
class. I feel the event should always be raised as it is the "responsible" thing to do.I found this thread on SO which kind of confirmed to me that it does not seem wrong to do so.
In addition I also run Code Analysis on that code to ensure I'm not breaking the CA1805 rule by initialising the EventHandler. CA1805 was not raised and no rules have been broken.
Using my car analogy from the comments, I believe not initializing the eventhandler and raising it all the time would be the same than saying "When turning a corner in your car only use your indicator if someone is watching and if not don't bother". You never know if anyone is watching, so you might as well make sure you always do it.
This is simply my personal preference. Anyone else, please do add the != null check at all times if that is how you prefere to do it.
Thank you so much for the comments ctacke and for pointing this out. I learned quite a lot from this.
I will have to go back to some of my projects now and update some code to make sure my libraries are not crashing if nobody subscribes to my events. I feel quite silly not ever having caught that in any of my Tests.
You can try this approach
If I ve not understood you wrong.I think you should try this way
I'm not sure if this is what you're after, but you can use the built in
Action
delegate type:Alternatively, use the standard event pattern and the
EventHandler<T>
delegate type. You'll need to create your ownEventArgs
type.