在 IL 中隐藏接口的 public 成员

Hiding public members of an interface in IL

考虑这些代码行:

ConcurrentDictionary<string, object> error = new ConcurrentDictionary<string, object>();
error.Add("hello", "world"); //actually throws a compiler error

IDictionary<string, object> noError = new ConcurrentDictionary<string, object>();
noError.Add("hello", "world");

我最终发现您所要做的就是更改 IL 以使 Add 函数私有。

现在,本着解耦代码的精神,我很可能会使用接口,但 Add 方法似乎并发词典不太常见。

真的使用安全吗Add(我看不到IL所以不知道是不是真的线程安全。)?或者我应该使用 ConcurrentDictionary<TKey, TValue> 的具体类型并显式使用 TryAdd.

是的,很安全。

看看reference source for ConcurrentDictionaryIDictionary<TKey, TValue>.Add 方法简单地调用 TryAdd 并在键已经存在时抛出异常。

接口成员的隐藏不需要修改 IL。它可以通过 C# 中的 explicit interface implementation 来完成。这是通过省略方法的访问修饰符并在方法名称前加上接口名称来完成的:

void IDictionary<TKey,TValue>.Add(TKey key, TValue value) {}

这样做有多种原因,也许您不想让具体界面混乱,或者您希望 class 的消费者明确说明他们使用的是什么方法,如果接口上的方法不够具体。此外,它允许您为具有相同签名的不同接口上的方法提供单独的实现(我认为 ConcurrentDictionary 并不是真正的问题,但如果您在自己的 classes 中需要它,该功能就在那里).

Hmya,你在玩危险的游戏。 ConcurrentDictionary class 的 public 接口提供了线程安全的方法,您可以放心调用它们,因为它们运行良好。

但是Add()方法不是这样的方法,只有TryAdd()是。您得到编译错误是因为 Add() 不是 public,Microsoft 故意 通过编写它的显式接口实现版本使该方法不可访问。否则他们必须做的事情,ConcurrentDictionary 实现 IDictionary。他们是否应该 实现了该接口是值得商榷的。但是桥上有水,他们做到了。

当然,您可以非常轻松地转换为访问 Add()。但现在这种感觉良好的感觉开始在边缘产生摩擦。非常恰当地,他们可以实现 Add() 的唯一方法是让它在 TryAdd() 失败时抛出异常。带有 ArgumentException 的 Kaboom,祝你调试顺利。

当这样的基本操作失败时,您是否绝对 100% 确定可以在工作线程上处理异常?您是否没有考虑破解 IL,而是考虑在 catch 子句中需要做什么?如果你这样做了,那么它与你在 TryAdd() returns false?

时编写的代码究竟有何不同?

不一样。