Подпись события в.NET — Используя сильного введенного 'отправителя'?

Самый быстрый путь - быстрее, чем исправлено ():

ДВА ПОПРАВКИ

x      = .123456
result = Math.round(x * 100) / 100  // result .12
<час>

ТРИ ПОПРАВКИ

x      = .123456
result = Math.round(x * 1000) / 1000      // result .123
106
задан Community 23 May 2017 в 12:34
поделиться

6 ответов

Я не согласен со следующими утверждениями:

  • Я считаю, что более старые версии Visual Basic .NET до 2005 года не имеют ковариации делегатов и контравариантности.
  • Я полностью осознаю, что это граничит с богохульством.

Прежде всего, ничто из того, что вы здесь сделали, не имеет ничего общего с ковариацией или контравариантностью. ( Изменить: Предыдущее утверждение неверно, для получения дополнительной информации см. Ковариация и контравариантность в делегатах ) Это решение будет отлично работать во всех версиях CLR 2.0 и выше (очевидно, что не работают в приложении CLR 1.0, поскольку оно использует универсальные шаблоны).

Во-вторых, я категорически не согласен с тем, что ваша идея граничит с «богохульством», поскольку это замечательная идея.

5
ответ дан 24 November 2019 в 03:53
поделиться

Я думаю, что это отличная идея, и MS может просто не иметь времени или интереса вкладывать средства в улучшение этого положения, например, когда они перешли с ArrayList на общие списки.

2
ответ дан 24 November 2019 в 03:53
поделиться

Я не думаю, что что-то не так с тем, что вы хотите сделать. По большей части, я подозреваю, что параметр отправителя объекта остается, чтобы продолжать поддерживать код до версии 2.0.

Если вы действительно хотите внести это изменение для общедоступного API, вы можете рассмотреть создание собственного базового класса EvenArgs. Примерно так:

public class DataEventArgs<TSender, TData> : EventArgs
{
    private readonly TSender sender, TData data;

    public DataEventArgs(TSender sender, TData data)
    {
        this.sender = sender;
        this.data = data;
    }

    public TSender Sender { get { return sender; } }
    public TData Data { get { return data; } }
}

Затем вы можете объявить свои события следующим образом

public event EventHandler<DataEventArgs<MyClass, int>> SomeIndexSelected;

И такие методы:

private void HandleSomething(object sender, EventArgs e)

по-прежнему смогут подписаться.

EDIT

Эта последняя строка заставила меня немного задуматься .. Фактически вы должны иметь возможность реализовать то, что вы предлагаете, без нарушения каких-либо внешних функций, поскольку среда выполнения не имеет проблем с понижением параметров. Я по-прежнему склоняюсь к решению DataEventArgs (лично). Я бы сделал это, но зная, что это излишне,

1
ответ дан 24 November 2019 в 03:53
поделиться

В текущей ситуации (отправитель - это объект) вы можете легко прикрепить метод к нескольким событиям:

button.Click += ClickHandler;
label.Click += ClickHandler;

void ClickHandler(object sender, EventArgs e) { ... }

Если бы отправитель был универсальным, целью события щелчка не было бы типа Button или Label, но типа Control (поскольку событие определено в Control). Таким образом, некоторые события в классе Button будут иметь цель типа Control, другие - другие типы целей.

1
ответ дан 24 November 2019 в 03:53
поделиться

Давай. Для кода, не основанного на компонентах, я часто упрощаю сигнатуры событий до простого

public event Action<MyEventType> EventName

, где MyEventType не наследуется от EventArgs . Зачем беспокоиться, если я никогда не собираюсь использовать какие-либо члены EventArgs.

1
ответ дан 24 November 2019 в 03:53
поделиться

То, что вы предлагаете, действительно имеет большой смысл, и я просто задаюсь вопросом, является ли это одной из тех вещей, которые просто таковы, потому что они были изначально разработаны до генериков, или настоящая причина для этого.

13
ответ дан 24 November 2019 в 03:53
поделиться