|
BillWoodruff wrote: Using them "raw," without the usual business/ceremony A multicast delegate* as a field (not focussing on it not residing in the class where the event is being invoked)
Let me first defend the event-pattern, that's easier; there's always a sender - it's an object, so there's no excuse for passing "null" there. Makes tracing stuff a lot easier. There's also probably a need for a list of parameters, but one can pass those as an object;
class MyArgs: EventArgs
{
public string Str1 {get;set;}
public string Str2 {get;set;}
} It is a clean and predictable pattern, which inherits nicely
"Clean" means that there's no 360-column list of arguments, but two - an object, and args (one with mayhaps 360 members).
BillWoodruff wrote: If you think such usage of Action and Func are very bad things, why ? Depends on where you do it, and why. If it has an advantage over other constructs, then it is automatically good.
Change the code to bind nothing to the field of the generic object, and run it. The field is called while being null. That could be bad, but without context that is hard to judge. The section on Events[^] also adds that it is thread-safe if there's more than one delegate bound to the invocation list.
MSDN magazine[^] has a good explanation on why there's more code in the pattern than in a raw delegate, and why. If for your class the "why" does not apply, then you have a good argumentation.
BillWoodruff wrote: Of course, if you assign an anonymous method as an EventHandler, you are
never going to be able to remove it from the delegate's method dispatch queue If you put your method in a delegate (say, a local variable or a field), and then bind it, you can also unbind it again using that reference. You can verify that by invoking the GetInvocationList[^] method on the delegate-field (of the generic object).
*) "Delegates with more than one method in their invocation list derive from MulticastDelegate, which is a subclass of System.Delegate", from MSDN[^].
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Thanks for your very thoughtful reply, Eddy; just the type of substantial response I was hoping for.
While I do admit to just generally "liking" the structure/behavior/use of Action, and Func Types, I am not on a "crusade" for using Action/Func as delegates in the way shown here; it's my nature to continually explore the language, and, by testing its/my limits, hopefully increase my own understanding.
I consider it possible that one response to this thread might be something related to thread-safety, or other aspects, of using Action/Func that I would have never been able to formulate which may revise my thoughts about their use.
"Delegates with more than one method in their invocation list derive from MulticastDelegate, which is a subclass of System.Delegate." I find this very interesting: I note, and show in the code example, that one can bind any number of methods to an Action or Func delegate: doesn't that mean they are also MultiCast ? Aren't all delegates inherently multi-cast ?
"If you put your method in a delegate (say, a local variable or a field), and then bind it, you can also unbind it again using that reference" I should have qualified my statement about the limitation possible by assigning an anonymous method to a Func/Action delegate by saying (the obvious): you cannot remove it if you have not kept a reference to it.
It's interesting to me that some third-party controls I use that expose Events really do not provide a practically useful object in the Events 'object sender parameter.
« There is only one difference between a madman and me. The madman thinks he is sane. I know I am mad. » Salvador Dali
|
|
|
|
|
BillWoodruff wrote: Thanks for your very thoughtful reply My pleasure, it was a fun question to answer. And come with code. And actual and expected results. Most people have items on their buglist that come with less information
BillWoodruff wrote: Aren't all delegates inherently multi-cast You can treat 'em like they are, even though the multicast-delegate appears to inherit from delegate. There's no inheritance-chain displayed on MSDN for other delegates. As far as I can see, every delegate has an invocation list. That would imply that each delegate could potentially be multicast.
BillWoodruff wrote: It's interesting to me that some third-party controls I use that expose Events
really do not provide a practically useful object in the Events 'object sender
parameter. We never touched the subject in school, so I expect that most programmers will not be very familiar with it.
..and it's not just third-party controls; WPF shows perfectly how Microsoft ignores its own recommendations.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Eddy Vluggen wrote: there's always a sender - it's an object, so there's no excuse for passing "null" there.
Static events?
Do not pass null as the sender parameter when raising a non-static event.
On static events, the sender parameter should be null .
Static events should pass null as the value of sender
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
It's a recommendation, and half a good one; try putting a static object into an object variable. There's no sense in boxing/unboxing if there's no object to box/unbox. Even the compiler thinks so.
Depending on the size of the project, I'd recommend passing the typeof(sumClassName).FullName as the sender there, which is allowed. It adds cost, of course, since one is fetching a property-value and boxing that.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
I usually use the EventHandler (or EventHandler<T> if I have any arguments to pass) type for events. This has a few advantages for me:
1. I follow a general pattern and know what to expect when I see it. I know I can subscribe and unsubscribe the events.
2. When Unit-Testing classes that handle events from other classes I can easily fake them using a mocking framework (NSubstitute is my preferred method) which already provides a very easy way to raise a certain event so I can test the behavior of my class.
Examples for firing events with NSubstitute: Link[^]
If the Event is of the type EventHandler I don't even have to specify any arguments as the framework passes the sender and EventArgs.Empty per default for me.
3. The IDE (maybe because of Resharper) helps me with creating the event invocators so I don't have to do that manually (or invoke the event without subscribers which might cause errors)
I do use Action and Func for other things though.
I regularly use(d) the Action when I code asynchronous things. I can just pass a method as a callback method (It's similiar to Microsofts pattern with the AsyncCallback type which is just a more specialized version of an Action). And I used Func for things like accessing an in memory list with Linq with different filters. (e.g. You could load the data from the cache etc. and reload from a data source if the cache has expired, etc.)
Example:
private List<MyObject> MyList;
void Main()
{
var items1 = Get(x => x.MyInt == 1);
var items2 = Get(x => x.MyBool == false);
var items3 = Get(x => x.MyString == "XXX");
var items4 = Get(x => x.MyBool == false && x.MyString == "XXX");
}
public IEnumerable<MyObject> Get(Func<MyObject, bool> filter) {
if(MyList == null) MyList = new List<MyObject>();
if(MyList.Count==0) {
MyList.Add(new MyObject { MyInt = 1, MyBool = true, MyString = "XXX" });
MyList.Add(new MyObject { MyInt = 2, MyBool = false, MyString = "XXX" });
MyList.Add(new MyObject { MyInt = 3, MyBool = false, MyString = "YYY" });
}
return MyList.Where(filter);
}
public class MyObject {
public int MyInt { get; set; }
public bool MyBool { get; set; }
public string MyString { get; set; }
}
This way I can handle the behaviour of accessing and loading the data in one central location.
So I usually use the Action and Func when I pass them as parameters to a method and the classic EventHandler for events.
|
|
|
|
|
I appreciate your response, Nicholas.
I also like to use a Func ... without making use of its multicast facilities ... to inject a callback method into some other Form/Class.
I recently advised someone here on this forum to do exactly that as a solution to his problem of needing to pass data from one form to another asynchronously: [^].
I have even gone so far as to make the callback Func defined in the "transmitter" object declared 'private and then have it set through a Public function called from the "receiver," with the intent of preventing any multi-cast usage of the Func. Probably an unnecessary caution considering I'm working alone, not in a team.
But, I guess if I were part of a team, on a large, complex, project, implementing Events in the usual way with custom EventArgs would probably pay off in the long-run. Possibly contributing to code consistency and maintainability ? Flexibility ?
« There is only one difference between a madman and me. The madman thinks he is sane. I know I am mad. » Salvador Dali
|
|
|
|
|
BillWoodruff wrote: But, I guess if I were part of a team, on a large, complex, project, implementing Events in the usual way with custom EventArgs would probably pay off in the long-run. Possibly contributing to code consistency and maintainability ? Flexibility ?
I think using the EventHandler pattern for all events induces some consistency at the least, because you can always subscribe to it in the same way. You don't need to do anything with the sender or the args parameter if you don't need to (but you can if you want).
Now lets consider a scenario where you just want to raise an event and react to that event in a very specific way. You don't need any parameters in that case at first but need to add parameters later (which you don't know when first implementing this)
Using the action
You use a simple Action to handle this event. You attach a handler and everything works fine. So far so good. Now you suddenly have the requirement to add a parameter to this value... uh.. alright. Change the signature of the Action to include the parameter and update every usage of it too... another parameter: same game again.
Using the EventHandler pattern
You use a standard EventHandler to Handle this event. Again, everything works fine. When the need arises to pass some arguments to the handler you can just change the signature of the EventHandler to include a custom EventArgs parameter. Without updating any references to it, everything is still working (at least if your parameter derives from System.EventArgs ) now you can change the signature of the method that handles the event and access the fields/properties of that parameter to do something based on that value. Another parameter. Just add an additional field and 'lo and behold: you didn't break any existing handler
Sure you can use the action to pass exactly one parameter with a data object the likes of an EventArgs parameter, but why go to that length when you could have used the EventHandler in the first place?
With the EventHandler you're pretty flexible in terms of adding (additional) arguments (or to remove some if you check if nobody actually uses the ones you want to remove) without having a lot of work to update any existing code. Sure it might seem like a bit of an overhead when writing it initially or a bit unnecessary to pass arguments that your handler doesn't actually need to process the event, but the coupling of those is a bit more loose than hard-wiring the actual method signature. I think even when working alone this might contribute to code that's easier to understand.
Of course, everything is very subjective for each individual programmer. Maybe for code you write and use only yourself it doesn't really matter. But maybe you have a public interface that is used by others or you see code that you've written a few years ago (of course there's alway the proper documentation available, right? ) So it might be wise to stick to a consistent style and maybe to follow a style that other do too, in case you have to use code written by others.
|
|
|
|
|
Thanks for this substantial, and eloquent, reply ! You make a solid case for using the standard EventHandler with EventArgs technique.
While you could just as well make use of a Func<param1, param2, param3, MyReturnClassInstance> and thus achieve an easily modifiable return value, at that point you are, arguably, duplicating the "standard model."
However, I will point out that the implementation of a revised EventArgs class, and using it, will also require changes to each place in your code that raises the Event: to initialize the new parameters.
cheers, Bill
« There is only one difference between a madman and me. The madman thinks he is sane. I know I am mad. » Salvador Dali
|
|
|
|
|
It's always a pleasure to have such a fine conversation with you.
BillWoodruff wrote: However, I will point out that the implementation of a revised EventArgs class, and using it, will also require changes to each place in your code that raises the Event: to initialize the new parameters.
I'm sorry that I have to contradict you on this matter. You only need to change the code where you actually want to access the values of the EventArgs parameter.
To underline my point I've included an example that illustrates my point. The text in bold mark the changes in comparison to the previous code block.
Basic implementation using the standard EventHandler
class Program {
static void Main(string[] args) {
var x = new MySender();
x.MyEvent += MyHandler;
}
private static void MyHandler(object sender, EventArgs eventArgs) {
}
}
public class MySender {
public event EventHandler MyEvent;
}
Change the definition of the EventHandler to custom EventArgs doesn't require you to change the code of the handler.
Make sure to derive the Custom EventArgs class from EventArgs or any other class that derives from EventArgs.
class Program {
static void Main(string[] args) {
var x = new MySender();
x.MyEvent += MyHandler;
}
private static void MyHandler(object sender, EventArgs eventArgs) {
}
}
public class MySender {
public event EventHandler<CustomArgs> MyEvent;
}
public class CustomArgs : EventArgs {
public int MyInt { get; set; }
}
Change the definition of the handler to access the EventArgs properties
class Program {
static void Main(string[] args) {
var x = new MySender();
x.MyEvent += MyHandler;
}
private static void MyHandler(object sender, CustomArgs eventArgs) {
var x = eventArgs.MyInt;
}
}
public class MySender {
public event EventHandler<CustomArgs> MyEvent;
}
public class CustomArgs : EventArgs {
public int MyInt { get; set; }
}
Cheers, Nicholas
|
|
|
|
|
Hi All,
Can we apply transaction rollback for active directory using c#.NET. If I trying to create a user in active directory and if any error occurs then user should not be created in active directory and all my changes should get roll backed. Is there way we can do this.
Can I use .net TransactionScope for this AD transaction?
Thanks,
Nitin
|
|
|
|
|
|
How to make custom pagination when use grid view in c#
|
|
|
|
|
|
It's not well-formed question. I'd like to say it's better to ask a question this way: "Why to use custom pagination?" or "What's the benefits of custom pagination?", but you need to:
1) have a minimal background (knowledge) about it,
2) provide a minimal information about your issue.
These two things are necessary if you want to be treated seriously.
So, at this moment i can advise you to look for solutions on the CP Knowledge Base[^].
|
|
|
|
|
am new to C#.net. i want to create the windows app that must contain the task-bar with icons related to them.can anyone solve my issue
modified 8-Oct-14 10:13am.
|
|
|
|
|
Edit: OP now moved, this message is irrelevant!.
modified 8-Oct-14 10:54am.
|
|
|
|
|
I think that strictly speaking this is more of a "wild eyed unfounded ambition" than a question - but I suppose it could be broken down into one ore more constituent questions.
|
|
|
|
|
Well then in that case, it's probably best you post in the right place.
(Hint:The Lounge, with it's banner proclaiming Technical discussions are welcome, but if you need specific help please use the programming forums. certainly isn't it.)
Try the C# forum, here: http://www.codeproject.com/Forums/1649/Csharp.aspx[^]
"When I was 5 years old, my mother always told me that happiness was the key to life. When I went to school, they asked me what I wanted to be when I grew up. I wrote down 'happy'. They told me I didn't understand the assignment, and I told them they didn't understand life." - John Lennon
|
|
|
|
|
Member 11117384 wrote: can anyone solve my issue More than likely, but they would expect to be paid. However, if you have a specific technical question, rather than a vague wishlist, then people will try to help you for free.
|
|
|
|
|
Hello
I have made a window form application using connection with sql database the application is ready to work in my computer. but when I was publish the project and also create a setup, then I am trying to install this project another computer then the application did not work. and the message show path not found
If you have an idea to solve this problem please share to me
Mohd Suhail
|
|
|
|
|
You haven't provided much in the way of detail. What exactly does the error message say, what are you trying to do when you get the error message etc.
Have you copied all the necessary files over to the other computer, does the code refer to a path that it can't access?
Please provide more details and we may be able to help.
|
|
|
|
|
The project is not running on my second computer. Only running on where it was build.
|
|
|
|
|
coolsuhail wrote: and the message show path not found A self-explanatory message, you are trying to access a file or folder which does not exist.
|
|
|
|
|
It could also be showing that he's lost in a forest, and that he's forgotten to leave a trail of gingerbread crumbs to find his way out with.
|
|
|
|
|