For simple, internal event handling, there are those that simply use Action
or Action<T>
, as you are proposing. I tend to use the standard pattern, including the Sender, even for internal events, because you never know when you might later want to expose a class or event, and I would not want the penalty of having to refactor the event method just to make it public.
I do agree with you that the event handling signature is a bit heavier than it should be for simple scenarios, but it is well designed to handle incremental migration as additional event arguments could become necessary over time. Overall, I would stick with the standard pattern, especially since, as you noted, you only get proper IntelliSense support if you do.
For what it's worth, I put some time into this and came up with a different event handling pattern: Event Signature in .NET — Using a Strong Typed 'Sender'?. The goal here was not to remove the Sender, but to make it generically strong typed as TSender
instead of weakly typed as System.Object
. It works very well; however, one does lose IntelliSense support when you do this, so there is an unfortunate trade-off.
Overall, I would stick with the standard pattern, but it is interesting to think about potentially better ways to do this.
In my opinion, your rule is a good one (or at least it's not a bad one), but only because of the situation you are describing. I wouldn't say that I agree with it in all situations, so, from the standpoint of my inner pedant, I'd have to say your rule is technically too broad.
Typically you wouldn't define immutable objects unless they are essentially being used as data transfer objects (DTO), which means that they contain data properties but very little logic and no dependencies. If that is the case, as it seems it is here, I'd say you are safe to use the concrete types directly rather than interfaces.
I'm sure there will be some unit-testing purists who will disagree, but in my opinion, DTO classes can be safely excluded from unit-testing and dependency-injection requirements. There is no need to use a factory to create a DTO, since it has no dependencies. If everything creates the DTOs directly as needed, then there's really no way to inject a different type anyway, so there's no need for an interface. And since they contain no logic, there's nothing to unit-test. Even if they do contain some logic, as long as they have no dependencies, then it should be trivial to unit-test the logic, if necessary.
As such, I think that making a rule that all DTO classes shall not implement an interface, while potentially unnecessary, is not going to hurt your software design. Since you have this requirement that the data needs to be immutable, and you cannot enforce that via an interface, then I would say it's totally legitimate to establish that rule as a coding standard.
The larger issue, though, is the need to strictly enforce a clean DTO layer. As long as your interface-less immutable classes only exist in the DTO layer, and your DTO layer remains free of logic and dependencies, then you will be safe. If you start mixing your layers, though, and you have interface-less classes that double as business layer classes, then I think you will start to run into much trouble.
Best Answer
As far as I know, declaring a helper method as a lambda like this is not commonly done in C#, so I would advise against doing this unless you have a good reason.
Good reasons include:
That being said, starting with C# 7.0, C# supports local functions, which are similar to such helper lambdas, but generally better: they have more succinct syntax and are more efficient. So if you used a local function for this purpose, I think that would be perfectly fine.