차이점을 이해하기 위해이 두 가지 예를 볼 수 있습니다.
대리자가있는 예 (이 경우 값을 반환하지 않는 대리자 유형의 작업)
public class Animal
{
public Action Run {get; set;}
public void RaiseEvent()
{
if (Run != null)
{
Run();
}
}
}
델리게이트를 사용하려면 다음과 같이해야합니다.
Animale animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();
이 코드는 잘 작동하지만 몇 가지 약점이있을 수 있습니다.
예를 들어 내가 이것을 쓰면
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
마지막 코드 줄로 이전 동작을 하나만 누락하여 재정의했습니다 +
( +
대신 사용 했습니다 +=
)
또 다른 약점은 당신의 Animal
클래스 를 사용하는 모든 클래스가 RaiseEvent
그것을 호출하는 것만으로도 올릴 수 있다는 것 animal.RaiseEvent()
입니다.
이 약점을 피하기 위해 events
C #에서 사용할 수 있습니다 .
당신의 동물 클래스는 이런 식으로 변경됩니다
public class ArgsSpecial :EventArgs
{
public ArgsSpecial (string val)
{
Operation=val;
}
public string Operation {get; set;}
}
public class Animal
{
public event EventHandler<ArgsSpecial> Run = delegate{} //empty delegate. In this way you are sure that value is always != null because no one outside of the class can change it
public void RaiseEvent()
{
Run(this, new ArgsSpecial("Run faster"));
}
}
이벤트 호출
Animale animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();
차이점 :
- 공용 속성이 아니라 공용 필드 (컴파일러가 원하지 않는 액세스로부터 필드를 보호하는 이벤트 포함)를 사용하고 있습니다.
- 이벤트는 직접 할당 할 수 없습니다. 이 경우 동작을 재정 의하여 보여준 이전 오류를 수행 할 수 없습니다.
- 클래스 외부의 누구도 이벤트를 제기 할 수 없습니다.
- 이벤트는 인터페이스 선언에 포함될 수 있지만 필드는
노트
EventHandler는 다음 대리자로 선언됩니다.
public delegate void EventHandler (object sender, EventArgs e)
보낸 사람 (객체 유형) 및 이벤트 인수를받습니다. 보낸 사람이 정적 메서드에서 가져온 경우 null입니다.
EventHAndler
대신이 예제를 사용할 수도 있습니다.EventHandler<ArgsSpecial>
EventHandler에 대한 문서는 여기 를 참조 하십시오.