Понимание событий и обработчиков событий в C#

Да, это может быть такая ситуация. Чтобы избежать этого, используйте LOCK / UNLOCK TABLE

$user = User::find(1);
if($user['balance']>250) {
    User::lockTable(); // method name/use depends on your framework
    // Here for example long loop
    $user->update([
        'balance' => DB:raw('balance - 100')
    ]);
    User::unlockTable();
}
309
задан Peter Mortensen 29 July 2012 в 11:59
поделиться

4 ответа

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

Центральным понятием делегата является его подпись или форма. Это (1) возвращаемый тип и (2) входные аргументы. Например, если мы создадим делегат void MyDelegate (отправитель объекта, EventArgs e) , он может указывать только на методы, которые возвращают void , и принимают объекты и EventArgs . Вроде как квадратное отверстие и квадратный колышек. Поэтому мы говорим, что эти методы имеют ту же сигнатуру или форму, что и делегат.

Итак, зная, как создать ссылку на метод, давайте подумаем о цели событий: мы хотим, чтобы какой-то код выполнялся, когда что-то происходит в другом месте в системе - или «обрабатывать событие». Для этого мы создаем специальные методы для кода, который мы хотим выполнить. Склейка между событием и выполняемыми методами - это делегаты. Событие должно внутренне хранить «список» указателей на методы, вызываемые при возникновении события. * Конечно, чтобы иметь возможность вызывать метод, нам нужно знать, какие аргументы передать ему! Мы используем делегата в качестве «контракта» между событием и всеми конкретными методами, которые будут вызваны.

Таким образом, по умолчанию EventHandler (и многим он нравится) представляет специфическую форму метода (снова void / object-EventArgs). Когда вы объявляете событие, вы говорите , какую форму метода (EventHandler) будет вызывать это событие, указав делегата:

//This delegate can be used to point to methods
//which return void and take a string.
public delegate void MyEventHandler(string foo);

//This event can cause any method which conforms
//to MyEventHandler to be called.
public event MyEventHandler SomethingHappened;

//Here is some code I want to be executed
//when SomethingHappened fires.
void HandleSomethingHappened(string foo)
{
    //Do some stuff
}

//I am creating a delegate (pointer) to HandleSomethingHappened
//and adding it to SomethingHappened's list of "Event Handlers".
myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);

//To raise the event within a method.
SomethingHappened("bar");

(* Это ключ к событиям в .NET и удаляет «магия» - событие действительно, под прикрытием, просто список методов одной и той же «формы». Список хранится там, где оно происходит. Когда событие «возбуждено», оно действительно просто «проходит через этот список». методов и вызывать каждый из них, используя эти значения в качестве параметров ". Назначение обработчика событий просто красивее,

624
ответ дан 23 November 2019 в 01:14
поделиться

Here is a code example which may help:

using System;
using System.Collections.Generic;
using System.Text;

namespace Event_Example
{
  // First we have to define a delegate that acts as a signature for the
  // function that is ultimately called when the event is triggered.
  // You will notice that the second parameter is of MyEventArgs type.
  // This object will contain information about the triggered event.

  public delegate void MyEventHandler(object source, MyEventArgs e);

  // This is a class which describes the event to the class that receives it.
  // An EventArgs class must always derive from System.EventArgs.

  public class MyEventArgs : EventArgs
  {
    private string EventInfo;

    public MyEventArgs(string Text) {
      EventInfo = Text;
    }

    public string GetInfo() {
      return EventInfo;
    }
  }

  // This next class is the one which contains an event and triggers it
  // once an action is performed. For example, lets trigger this event
  // once a variable is incremented over a particular value. Notice the
  // event uses the MyEventHandler delegate to create a signature
  // for the called function.

  public class MyClass
  {
    public event MyEventHandler OnMaximum;

    private int i;
    private int Maximum = 10;

    public int MyValue
    {
      get { return i; }
      set
      {
        if(value <= Maximum) {
          i = value;
        }
        else 
        {
          // To make sure we only trigger the event if a handler is present
          // we check the event to make sure it's not null.
          if(OnMaximum != null) {
            OnMaximum(this, new MyEventArgs("You've entered " +
              value.ToString() +
              ", but the maximum is " +
              Maximum.ToString()));
          }
        }
      }
    }
  }

  class Program
  {
    // This is the actual method that will be assigned to the event handler
    // within the above class. This is where we perform an action once the
    // event has been triggered.

    static void MaximumReached(object source, MyEventArgs e) {
      Console.WriteLine(e.GetInfo());
    }

    static void Main(string[] args) {
      // Now lets test the event contained in the above class.
      MyClass MyObject = new MyClass();
      MyObject.OnMaximum += new MyEventHandler(MaximumReached);
      for(int x = 0; x <= 15; x++) {
        MyObject.MyValue = x;
      }
      Console.ReadLine();
    }
  }
}
39
ответ дан 23 November 2019 в 01:14
поделиться

Это фактически объявление для обработчика событий - метода, который будет вызываться при запуске события. Чтобы создать событие, вы должны написать что-то вроде этого:

public class Foo
{
    public event EventHandler MyEvent;
}

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

Foo foo = new Foo();
foo.MyEvent += new EventHandler(this.OnMyEvent);

С помощью OnMyEvent (), определенным так:

private void OnMyEvent(object sender, EventArgs e)
{
    MessageBox.Show("MyEvent fired!");
}

Всякий раз, когда Foo срабатывает off MyEvent , затем будет вызван ваш обработчик OnMyEvent .

Вам не всегда нужно использовать экземпляр EventArgs в качестве второго параметра. Если вы хотите включить дополнительную информацию, вы можете использовать класс, полученный из EventArgs ( EventArgs является основой по соглашению). Например, если вы посмотрите на некоторые из событий, определенных в Control в WinForms или FrameworkElement в WPF,

36
ответ дан 23 November 2019 в 01:14
поделиться

C# knows two terms, delegate and event. Let's start with the first one.

Delegate

A delegate is a reference to a method. Just like you can create a reference to an instance:

MyClass instance = myFactory.GetInstance();

You can use a delegate to create an reference to a method:

Action myMethod = myFactory.GetInstance;

Now that you have this reference to a method, you can call the method via the reference:

MyClass instance = myMethod();

But why would you? You can also just call myFactory.GetInstance() directly. In this case you can. However, there are many cases to think about where you don't want the rest of the application to have knowledge of myFactory or to call myFactory.GetInstance() directly.

An obvious one is if you want to be able to replace myFactory.GetInstance() into myOfflineFakeFactory.GetInstance() from one central place (aka factory method pattern).

Factory method pattern

So, if you have a TheOtherClass class and it needs to use the myFactory.GetInstance(), this is how the code will look like without delegates (you'll need to let TheOtherClass know about the type of your myFactory):

TheOtherClass toc;
//...
toc.SetFactory(myFactory);


class TheOtherClass
{
   public void SetFactory(MyFactory factory)
   {
      // set here
   }

}

If you'd use delegates, you don't have to expose the type of my factory:

TheOtherClass toc;
//...
Action factoryMethod = myFactory.GetInstance;
toc.SetFactoryMethod(factoryMethod);


class TheOtherClass
{
   public void SetFactoryMethod(Action factoryMethod)
   {
      // set here
   }

}

Thus, you can give a delegate to some other class to use, without exposing your type to them. The only thing you're exposing is the signature of your method (how many parameters you have and such).

"Signature of my method", where did I hear that before? O yes, interfaces!!! interfaces describe the signature of a whole class. Think of delegates as describing the signature of only one method!

Another large difference between an interface and a delegate is that when you're writing your class, you don't have to say to C# "this method implements that type of delegate". With interfaces, you do need to say "this class implements that type of an interface".

Further, a delegate reference can (with some restrictions, see below) reference multiple methods (called MulticastDelegate). This means that when you call the delegate, multiple explicitly-attached methods will be executed. An object reference can always only reference to one object.

The restrictions for a MulticastDelegate are that the (method/delegate) signature should not have any return value (void) and the keywords out and ref is not used in the signature. Obviously, you can't call two methods that return a number and expect them to return the same number. Once the signature complies, the delegate is automatically a MulticastDelegate.

Event

Events are just properties (like the get;set; properties to instance fields) which expose subscription to the delegate from other objects. These properties, however, don't support get;set;. Instead, they support add; remove;

So you can have:

    Action myField;

    public event Action MyProperty
    {
        add { myField += value; }
        remove { myField -= value; }
    }

Usage in UI (WinForms,WPF,UWP So on)

So, now we know that a delegate is a reference to a method and that we can have an event to let the world know that they can give us their methods to be referenced from our delegate, and we are a UI button, then: we can ask anyone who is interested in whether I was clicked, to register their method with us (via the event we exposed). We can use all those methods that were given to us and reference them by our delegate. And then, we'll wait and wait.... until a user comes and clicks on that button, then we'll have enough reason to invoke the delegate. And because the delegate references all those methods given to us, all those methods will be invoked. We don't know what those methods do, nor we know which class implements those methods. All we do care about is that someone was interested in us being clicked, and gave us a reference to a method that complied with our desired signature.

Java

Languages like Java don't have delegates. They use interfaces instead. The way they do that is to ask anyone who is interested in 'us being clicked', to implement a certain interface (with a certain method we can call), then give us the whole instance that implements the interface. We keep a list of all objects implementing this interface and can call their 'certain method we can call' whenever we get clicked.

96
ответ дан 23 November 2019 в 01:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: