파생 클래스에서 기본 클래스 이벤트를 발생하는 방법(C# 프로그래밍 가이드)
다음 간단한 예제에서는 파생 클래스에서도 발생할 수 있도록 기본 클래스에서 이벤트를 선언하는 표준 방법을 보여 줍니다. 이 패턴은 .NET 클래스 라이브러리의 Windows Forms 클래스에서 광범위하게 사용됩니다.
다른 클래스의 기본 클래스로 사용할 수 있는 클래스를 만드는 경우 이벤트가 해당 이벤트를 선언한 클래스 내에서만 호출할 수 있는 특수 유형의 대리자라는 사실을 고려해야 합니다. 파생 클래스는 기본 클래스 내에서 선언된 이벤트를 직접 호출할 수 없습니다. 기본 클래스에서만 발생할 수 있는 이벤트를 원하는 경우도 있지만 대부분의 경우 파생 클래스가 기본 클래스 이벤트를 호출할 수 있도록 해야 합니다. 이렇게 하려면 이벤트를 래핑하는 기본 클래스에서 보호된 호출 메서드를 만듭니다. 이 호출 메서드를 호출하거나 재정의하면 파생 클래스에서 간접적으로 이벤트를 호출할 수 있습니다.
참고 항목
기본 클래스에서 가상 이벤트를 선언하지 말고 파생 클래스에서 재정의합니다. C# 컴파일러는 이러한 이벤트를 올바르게 처리하지 않으며, 파생 이벤트의 구독자가 실제로 기본 클래스 이벤트를 구독할지 여부를 예측할 수 없습니다.
예시
namespace BaseClassEvents
{
// Special EventArgs class to hold info about Shapes.
public class ShapeEventArgs : EventArgs
{
public ShapeEventArgs(double area)
{
NewArea = area;
}
public double NewArea { get; }
}
// Base class event publisher
public abstract class Shape
{
protected double _area;
public double Area
{
get => _area;
set => _area = value;
}
// The event. Note that by using the generic EventHandler<T> event type
// we do not need to declare a separate delegate type.
public event EventHandler<ShapeEventArgs> ShapeChanged;
public abstract void Draw();
//The event-invoking method that derived classes can override.
protected virtual void OnShapeChanged(ShapeEventArgs e)
{
// Safely raise the event for all subscribers
ShapeChanged?.Invoke(this, e);
}
}
public class Circle : Shape
{
private double _radius;
public Circle(double radius)
{
_radius = radius;
_area = 3.14 * _radius * _radius;
}
public void Update(double d)
{
_radius = d;
_area = 3.14 * _radius * _radius;
OnShapeChanged(new ShapeEventArgs(_area));
}
protected override void OnShapeChanged(ShapeEventArgs e)
{
// Do any circle-specific processing here.
// Call the base class event invocation method.
base.OnShapeChanged(e);
}
public override void Draw()
{
Console.WriteLine("Drawing a circle");
}
}
public class Rectangle : Shape
{
private double _length;
private double _width;
public Rectangle(double length, double width)
{
_length = length;
_width = width;
_area = _length * _width;
}
public void Update(double length, double width)
{
_length = length;
_width = width;
_area = _length * _width;
OnShapeChanged(new ShapeEventArgs(_area));
}
protected override void OnShapeChanged(ShapeEventArgs e)
{
// Do any rectangle-specific processing here.
// Call the base class event invocation method.
base.OnShapeChanged(e);
}
public override void Draw()
{
Console.WriteLine("Drawing a rectangle");
}
}
// Represents the surface on which the shapes are drawn
// Subscribes to shape events so that it knows
// when to redraw a shape.
public class ShapeContainer
{
private readonly List<Shape> _list;
public ShapeContainer()
{
_list = new List<Shape>();
}
public void AddShape(Shape shape)
{
_list.Add(shape);
// Subscribe to the base class event.
shape.ShapeChanged += HandleShapeChanged;
}
// ...Other methods to draw, resize, etc.
private void HandleShapeChanged(object sender, ShapeEventArgs e)
{
if (sender is Shape shape)
{
// Diagnostic message for demonstration purposes.
Console.WriteLine($"Received event. Shape area is now {e.NewArea}");
// Redraw the shape here.
shape.Draw();
}
}
}
class Test
{
static void Main()
{
//Create the event publishers and subscriber
var circle = new Circle(54);
var rectangle = new Rectangle(12, 9);
var container = new ShapeContainer();
// Add the shapes to the container.
container.AddShape(circle);
container.AddShape(rectangle);
// Cause some events to be raised.
circle.Update(57);
rectangle.Update(7, 7);
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
/* Output:
Received event. Shape area is now 10201.86
Drawing a circle
Received event. Shape area is now 49
Drawing a rectangle
*/
참고 항목
GitHub에서 Microsoft와 공동 작업
이 콘텐츠의 원본은 GitHub에서 찾을 수 있으며, 여기서 문제와 끌어오기 요청을 만들고 검토할 수도 있습니다. 자세한 내용은 참여자 가이드를 참조하세요.
.NET