Young87

SmartCat's Blog

So happy to code my life!

游戏开发交流QQ群号60398951

当前位置:首页 >AI写作

c#题例-2025-07-21 02:18:34

当然可以!以下是一道**专家级别**的 C# 程序员逻辑面试题,涵盖了 **委托、泛型、闭包、线程安全、异步编程** 等多个高级概念,适合考察候选人的综合编程能力与对 C# 语言特性的掌握深度。

---

### 🧠 面试题:实现一个线程安全的事件总线(Event Bus)系统

#### 背景描述:

你需要实现一个简单的**线程安全的事件总线(Event Bus)系统**,支持事件的发布与订阅。要求如下:

---

### 📌 要求:

1. **支持任意类型的事件(泛型)**
2. **支持异步订阅者(Func)**
3. **订阅和发布操作必须线程安全**
4. **订阅者在订阅后可以取消订阅**
5. **避免内存泄漏(如使用弱引用或正确管理取消机制)**
6. **支持多个订阅者同时监听同一事件类型**
7. **订阅者可以是异步的,发布事件时要并发执行所有订阅者的处理函数**

---

### 🧩 接口设计(你可以根据需要扩展):

```csharp
public interface IEventBus
{
IDisposable Subscribe(Func handler);
Task PublishAsync(TEvent @event, CancellationToken ct = default);
}
```

---

### ✅ 示例用法:

```csharp
var eventBus = new EventBus();

using (eventBus.Subscribe(async e =>
{
Console.WriteLine($"Received: {e.Message}");
await Task.Delay(100); // 模拟异步操作
}))
{
await eventBus.PublishAsync(new MyEvent { Message = "Hello World" });
}
```

---

### 🎯 面试官考察点:

1. **泛型委托的使用**:如何安全地处理 `Func`。
2. **线程安全**:使用 `ConcurrentDictionary`、锁、或 `Interlocked` 等机制保护事件订阅列表。
3. **IDisposable 实现**:如何优雅地取消订阅。
4. **异步并发处理**:在 `PublishAsync` 中如何并发执行多个异步订阅者。
5. **资源管理与内存泄漏防范**:是否使用了强引用导致订阅者无法被回收。
6. **异常处理**:订阅者抛出异常时如何处理(是否吞掉异常、是否继续执行其他订阅者)。
7. **CancellationToken 的处理**:是否考虑取消操作对发布的影响。

---

### 🧩 参考实现(简化版):

```csharp
public class EventBus : IEventBus
{
private readonly ConcurrentDictionary>>> _handlers =
new();

public IDisposable Subscribe(Func handler)
{
var type = typeof(TEvent);
var handlerList = _handlers.GetOrAdd(type, _ => new List>>());

var wrapper = new Func(o => handler((TEvent)o));

lock (handlerList)
{
handlerList.Add(new WeakReference>(wrapper));
}

return new Unsubscriber(() =>
{
lock (handlerList)
{
handlerList.RemoveAll(wr =>
{
if (wr.TryGetTarget(out var target))
return target == wrapper;
return true; // Remove dead references
});
}
});
}

public async Task PublishAsync(TEvent @event, CancellationToken ct = default)
{
var type = typeof(TEvent);
if (!_handlers.TryGetValue(type, out var handlerList))
return;

List> aliveHandlers;

lock (handlerList)
{
aliveHandlers = handlerList
.Where(wr => wr.TryGetTarget(out var target) ? (handlerList.Add(wr), true) : false)
.Select(wr => wr.Target!)
.ToList();
}

var tasks = aliveHandlers
.Select(h => h(@event))
.ToList();

await Task.WhenAll(tasks);
}

private class Unsubscriber : IDisposable
{
private readonly Action _unsubscribe;

public Unsubscriber(Action unsubscribe) => _unsubscribe = unsubscribe;

public void Dispose() => _unsubscribe();
}
}
```

---

### 🔁 可扩展问题(追问):

- 如何优化性能?(例如使用 `AsyncCollection` 或 `Channel`)
- 如何支持同步订阅者?
- 如何支持事件处理器的优先级?
- 如何支持事件继承(如基类事件也能被派生类触发)?

---

如果你需要我提供**更详细的实现讲解**或者**单元测试用例**,也可以告诉我!这个题目非常适合考察候选人的架构设计能力与语言深度掌握程度。

除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog

上一篇: c#题例-2025-07-21 07:51:47

下一篇: c#题例-2025-07-20 19:31:47

精华推荐