문제

C#, .NET 3.5를 사용하고 있습니다. 이벤트를 활용하는 방법, 수업에서 이벤트를 선언하는 방법, 다른 곳에서 연결하는 방법 등을 이해합니다.

public class MyList
{
    private List<string> m_Strings = new List<string>();
    public EventHandler<EventArgs> ElementAddedEvent;

    public void Add(string value)
    {
        m_Strings.Add(value);
        if (ElementAddedEvent != null)
            ElementAddedEvent(value, EventArgs.Empty);
    }
}

[TestClass]
public class TestMyList
{
    private bool m_Fired = false;

    [TestMethod]
    public void TestEvents()
    {
        MyList tmp = new MyList();
        tmp.ElementAddedEvent += new EventHandler<EventArgs>(Fired);
        tmp.Add("test");
        Assert.IsTrue(m_Fired);
    }

    private void Fired(object sender, EventArgs args)
    {
        m_Fired = true;
    }
}

그러나 내가하는 일 ~ 아니다 이해, 이벤트 핸들러를 선언 할 때입니다

public EventHandler<EventArgs> ElementAddedEvent;

초기화되지 않았습니다. 따라서 ElementAddedEvent는 정확히 무엇입니까? 그것은 무엇을 가리키나요? 이벤트 핸들러가 초기화되지 않기 때문에 다음은 작동하지 않습니다.

[TestClass]
public class TestMyList
{
    private bool m_Fired = false;

    [TestMethod]
    public void TestEvents()
    {
        EventHandler<EventArgs> somethingHappend;
        somethingHappend += new EventHandler<EventArgs>(Fired);
        somethingHappend(this, EventArgs.Empty);
        Assert.IsTrue(m_Fired);
    }

    private void Fired(object sender, EventArgs args)
    {
        m_Fired = true;
    }
}

EventHandler.createdElegate (...)가 있음을 알 수 있지만 모든 메소드 서명은 이것이 일반적인 ElementAddedEvent += New EventHandler (MyMethod)를 통해 이미 기존 이벤트 핸들러에 대의원을 첨부하는 데만 사용된다고 제안합니다.

확실하지 않습니다 무엇 나는 도움이 될 것입니다 ... 그러나 궁극적으로 나는 LINQ의 추상적 인 부모 데이터 콘텍스트를 생각해 내고 싶습니다. 유형에 따라 다릅니다. 이 같은:

public class BaseDataContext : DataContext
{
    private static Dictionary<Type, Dictionary<ChangeAction, EventHandler>> m_ObservedTypes = new Dictionary<Type, Dictionary<ChangeAction, EventHandler>>();

    public static void Observe(Type type)
    {
        if (m_ObservedTypes.ContainsKey(type) == false)
        {
            m_ObservedTypes.Add(type, new Dictionary<ChangeAction, EventHandler>());

            EventHandler eventHandler = EventHandler.CreateDelegate(typeof(EventHandler), null, null) as EventHandler;
            m_ObservedTypes[type].Add(ChangeAction.Insert, eventHandler);

            eventHandler = EventHandler.CreateDelegate(typeof(EventHandler), null, null) as EventHandler;
            m_ObservedTypes[type].Add(ChangeAction.Update, eventHandler);

            eventHandler = EventHandler.CreateDelegate(typeof(EventHandler), null, null) as EventHandler;
            m_ObservedTypes[type].Add(ChangeAction.Delete, eventHandler);
        }
    }

    public static Dictionary<Type, Dictionary<ChangeAction, EventHandler>> Events
    {
        get { return m_ObservedTypes; }
    }
}


public class MyClass
{
    public MyClass()
    {
        BaseDataContext.Events[typeof(User)][ChangeAction.Update] += new EventHandler(OnUserUpdate);
    }

    public void OnUserUpdated(object sender, EventArgs args)
    {
        // do something
    }
}

이것에 대해 생각하면 나는 이벤트와 함께 HOD에서 무슨 일이 일어나고 있는지 이해하지 못한다는 것을 깨달았습니다. 그리고 나는 이해하고 싶습니다 :)

도움이 되었습니까?

해결책

나는 이것을 상당한 양의 세부적으로 썼다. 기사,하지만 여기 요약이 있습니다. 대표 그들 자신:

  • 이벤트는 속성이 실제로 "get"메소드이고 "세트"메소드 인 것과 같은 방식으로 "추가"메소드와 "제거"메소드입니다. (실제로 CLI는 "Raise/Fire"방법도 허용하지만 C#은 이것을 생성하지 않습니다.) 메타 데이터는 메소드에 대한 참조로 이벤트를 설명합니다.
  • 당신이 선언 할 때 a 현장과 같은 이벤트 (ElementAddedEvent와 마찬가지로) 컴파일러는 메소드를 생성합니다. 그리고 개인 분야 (대의원과 같은 유형). 수업 내에서 ElementAddedEvent를 언급 할 때 필드를 언급합니다. 수업 밖에서, 당신은 현장을 언급하고 있습니다.
  • 누구나 추가 메소드를 호출하는 이벤트 ( += 연산자 포함)를 구독 할 때. 제거를 취소 할 때 ( -= 연산자와 함께) 제거를 호출합니다.
  • 필드와 같은 이벤트의 경우 약간의 동기화가 있지만 추가/제거는 대의원을 호출합니다.결합하다/제거하다 자동 생성 된 필드의 값을 변경합니다. 이 두 가지 작업은 후원장에 할당됩니다. 대표는 불변이라는 것을 기억하십시오. 다시 말해,자가 생성 코드는 다음과 매우 흡사합니다.

    // Backing field
    // The underscores just make it simpler to see what's going on here.
    // In the rest of your source code for this class, if you refer to
    // ElementAddedEvent, you're really referring to this field.
    private EventHandler<EventArgs> __ElementAddedEvent;
    
    // Actual event
    public EventHandler<EventArgs> ElementAddedEvent
    {
        add
        {
            lock(this)
            {
                // Equivalent to __ElementAddedEvent += value;
                __ElementAddedEvent = Delegate.Combine(__ElementAddedEvent, value);
            }
        }
        remove
        {
            lock(this)
            {
                // Equivalent to __ElementAddedEvent -= value;
                __ElementAddedEvent = Delegate.Remove(__ElementAddedEvent, value);
            }
        }
    }
    
  • 귀하의 경우 생성 된 필드의 초기 값은 null - 그리고 그것은 항상 될 것입니다 null 모든 가입자가 제거 된 경우 다시는 Delegate.remove의 동작입니다.

  • "No-OP"핸들러가 이벤트를 구독하여 무효 점검을 피하기 위해 다음을 수행 할 수 있습니다.

    public EventHandler<EventArgs> ElementAddedEvent = delegate {};
    

    그만큼 delegate {} 매개 변수를 신경 쓰지 않고 아무것도하지 않는 익명의 방법입니다.

여전히 불분명 한 것이 있다면 물어 보시면 도와 드리겠습니다!

다른 팁

후드 아래에서, 이벤트는 특별한 전화 규칙이있는 대의원 일뿐입니다. (예를 들어, 이벤트를 제기하기 전에 무효 점을 확인할 필요가 없습니다.)

pseudocode에서 event.invoke ()는 다음과 같이 분해됩니다.

이벤트에 청취자 가이 스레드에서 각 청취자를 동기식으로 호출하는 경우 임의 순서로.

이벤트는 멀티 캐스트이므로 컬렉션에 개최 된 리스너 이상이 0 이상이됩니다. CLR은 그들을 통과하여 각각 임의의 순서로 호출합니다.

기억해야 할 큰 경고 중 하나는 이벤트 핸들러가 이벤트가 제기되는 것과 동일한 스레드에서 실행된다는 것입니다. 새로운 스레드를 산란하는 것으로 생각하는 것은 일반적인 정신적 오류입니다. 그들은하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top