Насколько неправильно создавать делегат обработчика событий без стандартной подписи (Obj sender, EventArgs args)?
Я понимаю преимущества использования стандартной подписи делегата обработчика событий MS, поскольку она позволяет легко расширять информацию, передаваемую через событие, без разрыва любых старых отношений, основанных на старой подписи делегата.
На практике мне интересно, как часто люди следуют этому правилу? Скажем, у меня есть простое событие, как это
public event NameChangedHandler NameChanged;
public delegate void NameChangedHandler(Object sender, string oldName, string newName);
Это простое событие, и я почти уверен, что единственные аргументы, которые мне когда-либо понадобятся узнать из события NameChanged, - это объект, имя которого изменилось, старое имя и новое имя. Так стоит ли создавать отдельный класс NameChangedEventArgs или для простых событий, подобных этому, допустимо просто возвращать аргументы напрямую через аргументы делегата?
3 ответа
Вы можете сделать что-то неправильно, если вы единственный, кто имеет дело с этим. Но неплохо было бы выучить стандарты и придерживаться их, чтобы сохранить хорошие привычки при работе над кодом с другими.
Так что я заключу с тобой сделку. Если вы пообещаете сделать это правильно, я дам вам фрагмент кода, который облегчит вам задачу. Просто поместите это в файл.snippet и поместите этот файл в:
Мои документы \Visual Studio 2008\ Фрагменты кода \Visual C#\ Фрагменты кода \
(или Visual Studio 2005, если применимо)
А вот и фрагмент; используйте его в VS, набрав ev2Generic и нажав Tab:
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Generic event with two types/arguments.</Title>
<Shortcut>ev2Generic</Shortcut>
<Description>Code snippet for event handler and On method</Description>
<Author>Kyralessa</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type1</ID>
<ToolTip>Type of the first property in the EventArgs subclass.</ToolTip>
<Default>propertyType1</Default>
</Literal>
<Literal>
<ID>arg1Name</ID>
<ToolTip>Name of the first argument in the EventArgs subclass constructor.</ToolTip>
<Default>property1Name</Default>
</Literal>
<Literal>
<ID>property1Name</ID>
<ToolTip>Name of the first property in the EventArgs subclass.</ToolTip>
<Default>Property1Name</Default>
</Literal>
<Literal>
<ID>type2</ID>
<ToolTip>Type of the second property in the EventArgs subclass.</ToolTip>
<Default>propertyType2</Default>
</Literal>
<Literal>
<ID>arg2Name</ID>
<ToolTip>Name of the second argument in the EventArgs subclass constructor.</ToolTip>
<Default>property2Name</Default>
</Literal>
<Literal>
<ID>property2Name</ID>
<ToolTip>Name of the second property in the EventArgs subclass.</ToolTip>
<Default>Property2Name</Default>
</Literal>
<Literal>
<ID>eventName</ID>
<ToolTip>Name of the event</ToolTip>
<Default>NameOfEvent</Default>
</Literal>
</Declarations>
<Code Language="CSharp">
<![CDATA[public class $eventName$EventArgs : System.EventArgs
{
public $eventName$EventArgs($type1$ $arg1Name$, $type2$ $arg2Name$)
{
this.$property1Name$ = $arg1Name$;
this.$property2Name$ = $arg2Name$;
}
public $type1$ $property1Name$ { get; private set; }
public $type2$ $property2Name$ { get; private set; }
}
public event EventHandler<$eventName$EventArgs> $eventName$;
protected virtual void On$eventName$($eventName$EventArgs e)
{
var handler = $eventName$;
if (handler != null)
handler(this, e);
}]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
Использовать EventHandler<T>
общие делегаты для ваших событий и создать тип, производный от EventArgs
держать ваши данные события. Иными словами, всегда. Это то, что вы всегда точно знаете, как это работает, когда сталкиваетесь с этим, потому что это никогда не делается иначе.
Редактировать:
Анализ кода CA1003: использование общих экземпляров обработчика событий
Анализ кода CA1009: правильно объявить обработчики событий
На практике, как часто люди [не используют производные классы EventArgs].
Я никогда не сталкивался со временем, когда производные классы EventArgs не использовались. Как вы говорите сами, это увеличивает вашу способность изменить свой код позже. Я также утверждал бы, что читаемость улучшена, так как легко видеть, что это обработчик событий.
Стоит ли создавать отдельный класс NameChangedEventArgs или для простых событий, подобных этому, допустимо просто возвращать аргументы непосредственно через аргументы делегата?
Вы, кажется, говорите, что использовали бы EventArgs для обработчиков событий с большим количеством параметров и не использовали бы его для подобных случаев. Честно говоря, это просто не вариант при программировании на C#. Согласованность необходима, особенно в современном мире форумов, таких как проекты с открытым исходным кодом и т. Д., Где ее легко потерять. Конечно, если вы программируете это под рок, вы можете делать все, что захотите, но сообщество C# поблагодарит вас за соблюдение стандартов и, в особенности, за использование последовательности в вашем коде.