Почему и при использовании событий? - PullRequest
2 голосов
/ 29 июня 2010

В моем личном проекте я никогда не использовал Events. Я никогда не чувствовал его необходимости. Особенно использование Events создает некоторые проблемы с ограничением для методов с одинаковыми параметрами, и именно поэтому я не использовал его. используй это ? Когда и где нам это нужно?

Редактировать: Использование событий больше для закрытых исходных библиотек? Потому что мы не можем прикрепить какой-либо метод к существующим методам с закрытым исходным кодом, чтобы события помогли нам решить эту проблему? Потому что в открытом исходном коде мы можем легко добавить наши методы в конец методов.

Ответы [ 5 ]

5 голосов
/ 29 июня 2010

О, у меня была та же проблема.Я понял концепцию событий, потому что я интенсивно использовал их в JavaScript, но я просто не мог оправдать использование событий в приложении C #.Я имею в виду, я использовал сервер OnClick и т. Д., Но я не мог понять, зачем мне использовать события где-либо еще.

На самом деле забавная история, потому что я усвоил ее нелегко, работая над своей игрой ORPG,Рассмотрим следующий код:

class Player
{
    private int health;
    public int Health
    {
        get
        {
            if (health <= 0)
            {
                Die();
            }

            return health;

        }

        set
        {
            health = value;
        }
    }

    public void Die()
    {
        // OMG I DIED, Call bunch of other methods:
        // RemoveFromMap();
        // DropEquipment(); etc
    }
}

Имеет смысл, верно?У игрока нет здоровья, поэтому я звоню Die().Затем метод Die делает все, что должен - убить игрока.

Мои проблемы начались, когда я захотел повторно использовать этот класс в приложении Server и Client моей игры ORPG.Довольно легко заметить, что метод Die() должен выполнять разные вещи, в зависимости от того, где выполняется 'Kill' - на сервере он должен обновлять все виды различных данных - на клиенте он должен делать что-то с графикой.

Дополнительно - что, если бы я хотел, чтобы метод Die() делал разные вещи, в зависимости от типа проигрывателя?После того, как все контролируемые пользователем игроки должны делать разные вещи, когда их убивают, по сравнению с игроками, контролируемыми компьютером / ИИ (NPC).

И вот, я был вынужден использовать события:

class Player
{
    public event DieHandler Die;
    public delegate void DieHandler(Player sender, EventArgs e);
    public virtual void OnDie(EventArgs e)
    {
        if (Die != null)
            Die(this, e);
    }

    private int health;
    public int Health
    {
        get
        {
            if (health <= 0)
            {
                onDie(new EventArgs());
            }

            return health;

        }

        set
        {
            health = value;
        }
    }
}

Итеперь, когда я создаю нового игрока, я могу назначить любой метод для его DieHandler:

Player player = new Player("Joe");
player.Die += Client.Players.PlayerDie;

Player npc = new Player("Cookie Monster");
npc.Die += Client.Npcs.NpcDie;

, где Client.Npcs.Die и Client.Players.Die - один из следующих:

public void NpcDie(Player sender, EventArgs e)
{
    //who hoo, I can be implemented differently
    //I can even check if sender.Health <= 0
}

public void PlayerDie(Player sender, EventArgs e)
{
}

Как вы можете видеть, теперь у нас есть гибкость, позволяющая присоединить любой «подходящий» метод к нашему обработчику Die.Мы отправляем объект Player в качестве атрибута отправителя и любой определенный EventArgs в e.Мы можем использовать EventArgs для отправки дополнительной информации, например - e.NameOfTheKiller, e.LastHitAtTime и т. Д. Лучше всего то, что вы можете определить свой собственный класс EventArgs, чтобы вы могли отправлять дополнительную информацию, когда вы создаете событие.

Ух ты ... этот пост длинный.Я надеюсь, что вы получите это сейчас.

Опять же - используйте события везде, когда вы хотите «сообщить внешнему миру» о каком-то конкретном состоянии вашего объекта и соответствующим образом обработать это изменение.Это сделает ваш код более гибким и намного проще в обслуживании.

1 голос
/ 29 июня 2010

Наиболее очевидный пример, события особенно полезны при работе с GUI. Пользователь вашего приложения обычно взаимодействует с интерфейсной частью вашего кода (в данном случае с графическим интерфейсом), в то время как большая часть логики «скрыта».

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

Та же история с пользовательским интерфейсом. В большинстве случаев ему не нужно знать (и не следует), как именно реализована логика приложения или что она делает. Это там, чтобы представить результаты и взаимодействовать с пользователем.

Как это работает в .NET? Рассмотрим продолжение примера бронирования билетов, часть, скажем, TicketBooker класса:

public event Action BookingSuccessful;

public void BookTicket()
{
    // lot of complex steps that should run in background
    this.ValidateInputData();
    this.GetTicketInfo();
    this.CheckUserInfo();
    this.SendDataToOperator();
    this.WithdrawMoney(); 
    // ...and perhaps lot more stuff you might want to do 
    // in order to book ticket
    if (booked)
    {
        // we're done: let's raise event which will 
        // notify all interested observers 
        this.BookingSuccessful();
    }
}

Как видите, метод BookTicket может занять много времени, может иметь много сложных шагов, большинство из которых - как пользователь - мы не хотим знать. Нам просто нужна информация, забронировали мы ее или нет.

Зная это, мы не хотим, чтобы пользователь ждал с зависшим приложением, потому что билет забронирован. Пользователь по-прежнему должен иметь возможность взаимодействовать с ним (в некоторой степени, конечно). Следовательно, классы пользовательского интерфейса хотят подписаться на TicketBooker событие класса.

TicketBooker tb = new TicketBooker();
tb.BookingSuccessful += this.ShowSuccessMessage;

// ... somewhere here we call tb.BookTicket() method to run in background
// once it completes (with success), it will raise BookingSuccessful event
// which will cause ShowSuccessMessage to execute, as we subscribed it

public void ShowSuccessMessage()
{
    // simply display success message in interface, eg. by setting label text
}

Более полная картина, конечно, намного больше, чем в этом простом примере. События помогают отделить слой представления приложения от модели данных / бизнес-логики, они имеют дело с уведомлением заинтересованных объектов об изменениях в ваших объектах и ​​так далее.

Для начала, вы можете проверить этот учебник на MSDN: Учебник событий

Проверка работы шаблона Model-View-Controller также может помочь лучше понять: MVC .

И, как всегда, SO полон ресурсов по этой теме, просто ищите вопросы с тегами events & .net .

1 голос
/ 29 июня 2010

Вам не нужно его использовать.Тем не менее, это всего лишь ярлык для того, что вы в конечном итоге будете делать, если проблема, которую вы решаете, требует этого.Но так как вы используете C # .NET с ярлыками, вам будет лучше их использовать.Это больше C # иш.

1 голос
/ 29 июня 2010

Хорошо, когда вам нужно, чтобы наблюдатели реагировали на события, которые происходят внутри ваших объектов:)

Наиболее очевидными примерами являются компоненты пользовательского интерфейса - Button представляет событие, которое вызывается, например, при нажатии кнопки.

Если у вас нет ничего, что естественно чувствует , как будто оно выставляет события, тогда не стоит их использовать. Однако, если у вас есть что-то, в чем другие стороны заинтересованы в реакции на события, происходящие в ваших объектах, вам следует учитывать события - и / или структуру Reactive Extensions .

0 голосов
/ 29 июня 2010

События используются для обратных вызовов, когда сервер может вызвать метод клиента. Такая опция существует не только в c # (например, указатели на функции в c ++). Конечно, вы не можете использовать события для создания кода, избегая их. Я бы рекомендовал узнать их поближе и понять их преимущества.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...