事件 #
一、事件概述 #
1.1 什么是事件 #
事件是对象发出的通知,表示发生了某件事情。
1.2 事件特点 #
- 发布-订阅模式
- 类型安全
- 支持多订阅者
- 封装委托
二、定义事件 #
2.1 基本语法 #
csharp
public class Button
{
public event EventHandler? Clicked;
public void Click()
{
Clicked?.Invoke(this, EventArgs.Empty);
}
}
var button = new Button();
button.Clicked += (sender, e) =>
{
Console.WriteLine("按钮被点击");
};
button.Click();
2.2 自定义事件参数 #
csharp
public class PriceChangedEventArgs : EventArgs
{
public decimal OldPrice { get; }
public decimal NewPrice { get; }
public PriceChangedEventArgs(decimal oldPrice, decimal newPrice)
{
OldPrice = oldPrice;
NewPrice = newPrice;
}
}
public class Stock
{
private decimal _price;
public event EventHandler<PriceChangedEventArgs>? PriceChanged;
public decimal Price
{
get => _price;
set
{
if (_price != value)
{
var oldPrice = _price;
_price = value;
OnPriceChanged(oldPrice, value);
}
}
}
protected virtual void OnPriceChanged(decimal oldPrice, decimal newPrice)
{
PriceChanged?.Invoke(this, new PriceChangedEventArgs(oldPrice, newPrice));
}
}
三、订阅事件 #
3.1 订阅和取消订阅 #
csharp
var stock = new Stock();
EventHandler<PriceChangedEventArgs> handler = (sender, e) =>
{
Console.WriteLine($"价格从 {e.OldPrice} 变为 {e.NewPrice}");
};
stock.PriceChanged += handler;
stock.Price = 100;
stock.PriceChanged -= handler;
3.2 方法订阅 #
csharp
var stock = new Stock();
stock.PriceChanged += OnPriceChanged;
stock.PriceChanged -= OnPriceChanged;
void OnPriceChanged(object? sender, PriceChangedEventArgs e)
{
Console.WriteLine($"价格变化: {e.OldPrice} -> {e.NewPrice}");
}
四、标准事件模式 #
4.1 EventHandler #
csharp
public class ProcessCompletedEventArgs : EventArgs
{
public bool IsSuccessful { get; }
public string Message { get; }
public ProcessCompletedEventArgs(bool isSuccessful, string message)
{
IsSuccessful = isSuccessful;
Message = message;
}
}
public class Process
{
public event EventHandler<ProcessCompletedEventArgs>? ProcessCompleted;
public void Start()
{
Console.WriteLine("处理开始...");
Thread.Sleep(1000);
OnProcessCompleted(true, "处理成功");
}
protected virtual void OnProcessCompleted(bool isSuccessful, string message)
{
ProcessCompleted?.Invoke(this, new ProcessCompletedEventArgs(isSuccessful, message));
}
}
4.2 线程安全触发 #
csharp
public class SafeEventPublisher
{
public event EventHandler? SomethingHappened;
public void RaiseEvent()
{
var handler = Volatile.Read(ref SomethingHappened);
handler?.Invoke(this, EventArgs.Empty);
}
}
五、事件访问器 #
5.1 自定义事件访问器 #
csharp
public class CustomEventPublisher
{
private EventHandler? _myEvent;
public event EventHandler MyEvent
{
add
{
lock (this)
{
_myEvent += value;
}
}
remove
{
lock (this)
{
_myEvent -= value;
}
}
}
protected virtual void OnMyEvent()
{
_myEvent?.Invoke(this, EventArgs.Empty);
}
}
六、实战示例 #
6.1 文件监控器 #
csharp
public class FileMonitor
{
public event EventHandler<FileChangedEventArgs>? FileChanged;
private readonly FileSystemWatcher _watcher;
public FileMonitor(string path)
{
_watcher = new FileSystemWatcher(path)
{
EnableRaisingEvents = true
};
_watcher.Changed += OnFileChanged;
_watcher.Created += OnFileChanged;
_watcher.Deleted += OnFileChanged;
}
private void OnFileChanged(object sender, FileSystemEventArgs e)
{
FileChanged?.Invoke(this, new FileChangedEventArgs(e.FullPath, e.ChangeType));
}
}
public class FileChangedEventArgs : EventArgs
{
public string FilePath { get; }
public WatcherChangeTypes ChangeType { get; }
public FileChangedEventArgs(string filePath, WatcherChangeTypes changeType)
{
FilePath = filePath;
ChangeType = changeType;
}
}
6.2 进度报告 #
csharp
public class ProgressReporter
{
public event EventHandler<ProgressEventArgs>? ProgressChanged;
public async Task ProcessAsync(int total)
{
for (int i = 0; i <= total; i++)
{
await Task.Delay(100);
OnProgressChanged(i, total);
}
}
protected virtual void OnProgressChanged(int current, int total)
{
var percent = (double)current / total * 100;
ProgressChanged?.Invoke(this, new ProgressEventArgs(current, total, percent));
}
}
public class ProgressEventArgs : EventArgs
{
public int Current { get; }
public int Total { get; }
public double Percent { get; }
public ProgressEventArgs(int current, int total, double percent)
{
Current = current;
Total = total;
Percent = percent;
}
}
七、总结 #
事件要点:
| 要点 | 说明 |
|---|---|
| event | 定义事件 |
| EventHandler | 标准委托 |
| EventArgs | 事件参数 |
| += -= | 订阅取消 |
| Invoke | 触发事件 |
下一步,让我们学习Lambda表达式!
最后更新:2026-03-26