New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Addition of generic event arguments class #49435
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Could be a generic version of namespace System
{
public class EventArgs<T> : EventArgs
{
public T OldValue { get; }
public T NewValue { get; }
public EventArgs(T oldValue, T newValue)
{
OldValue = oldValue;
NewValue = newValue;
}
}
public delegate void EventHandler<T>(object sender, EventArgs<T> e);
} |
@benaadams Yeah I like that naming better I forget we could use EventArgs still if using a type parameter. I'll change that around in a few and commit that. Why the type parameters on the delegate? Specifically the first one. Pull Request #49436 |
To specify the type of the value for consumers of the event public class MyComponent
{
public event EventHandler<string> NameChanged;
}
public class MyClass
{
private MyComponent _component;
public MyClass()
{
_component = new();
_component.NameChanged += NameChanged;
}
private void NameChanged(object sender, EventArgs<string> e)
{
throw new NotImplementedException();
}
} |
Oh right of course! Yeah I'm changing that right now and I'll submit that shortly. |
I messed up the earlier pull request so I closed it and remade it #49438. |
Personally, I don't think the |
In some cases in may cost a lot but in those cases something else more suitable should be used. I do find this pattern very useful quite often though. I have seen many scenarios in which it shouldn't be used of course. But the same could be said for anything really. I don't always use just one pattern though. I use what is appropriate for that situation. |
Thank you @jeffschwMSFT I wasn't sure which area it fell under. So to clarify for the future anything under the system namespace would fall under that label? |
@Hawkeye4040 area-System.Runtime is a little of a catch-all, but using the simple heuristic of things directly in the System namespace is a reasonable proxy. cc @jeffhandley |
I wouldn't expect With |
Also worth mentioning, but I don't love it myself. 😉 namespace System
{
public class EventArgs<T> : EventArgs
{
public T Value { get; }
public EventArgs(T value)
{
Value = value;
}
}
}
namespace App
{
public class MyClass
{
private MyComponent _component;
public MyClass()
{
_component = new();
_component.NameChanged += NameChanged;
}
private void NameChanged(object sender EventArgs<(string OldValue, string NewValue)> e)
{
Console.WriteLine($"OldValue: {e.Value.OldValue}. NewValue: {e.Value.NewValue}.");
}
}
} |
So namespace System
{
public struct ValueChangedEventArgs<T>
{
public T OldValue { get; }
public T NewValue { get; }
public EventArgs(T oldValue, T newValue)
{
OldValue = oldValue;
NewValue = newValue;
}
}
public delegate void ValueChangedEventHandler<T>(object? sender, ValueChangedEventArgs<T> e);
} |
Ha that's funny because |
I like the idea of a struct there. I haven't given that much thought yet but I will. What about considerations surrounding value type vs reference type here? |
@benaadams Note that this goes against the Framework Design Guidelines:
Not every API has to follow the FDG (especially for guidelines that are almost 20 years old), but I think violating them should have a pretty good justification. |
Also, this introduces a new API for notifications of property changes, when there already is one: Would it be better to extend |
@svick I'm proposing something a little different here than extending As for the guidelines part. I hardly believe in following something that's 20 years old when over those years so much has changed. I'm not saying there aren't parts that are still relevant but it's also not going to be the programmers commandments either. |
I can't get the struct idea out of my head. I really like it for a lot of reasons. I want to say there's a reason not to do it that way but I'm drawing a blank on it. I've poured over many articles such as this one and read various manuals/publications covering the topic. I really can't find anything wrong with it, I like it I don't see how it goes against the Framework Design Guidelines exactly. Can anyone clarify on that more? I feel like there's something off there I'm just forgetting. |
Background and Motivation
I find myself writing basic event arguments classes often in order to wire up object changed events in my classes often. When no other data is needed I've found that a generic event arguments class works well here. Rather than storing them in a "core" library of mine it makes sense to add this particular class to the .NET Runtime itself.
Proposed API
Usage Examples
Alternative Designs
Prior to a generic event arguments class I would find myself often writing out classes needlessly to simply store an old value and new value. This one class can be used to fire events on property changes easily as shown above in the usage example. If other properties such as timestamps are needed either this class or EventArgs could be derived from.
On a side note a better class name could be used, I just haven't been able to think of one yet. I feel a better, more fitting name is out there for this class though.
Risks
No known risks.
The text was updated successfully, but these errors were encountered: