在IL中隐藏接口的公共成员

4

考虑以下代码:

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函数设置为私有。

现在,在分离的代码精神中,我很可能会使用接口,但似乎并不太适用于Concurrent dictionary 的 Add方法。

使用Add是否安全(我无法查看IL,因此不知道它是否真正是线程安全的)?还是应该使用ConcurrentDictionary<TKey,TValue>的具体类型,并显式地使用TryAdd


2
你的标题和实际问题并不匹配。接口中不存在非公共成员 - Erik Philips
@ErikPhilips 不确定链接与此相关。很明显IDictionary<,>公开了Add,但Concurrent Dictionary没有,这意味着它实现了接口,但该函数仍然被隐藏。 - dbarnes
它并不是隐藏的。你需要理解隐式实现与显式实现之间的区别。在任何情况下,“Add()”都是已实现并公开的。 - Erik Philips
@evanmcdonnal 我猜他们使用的是Sandcastle,它不会寻找显式定义,但我认为这个答案超出了这个问题的范围。 - dbarnes
2
@evanmcdonnal,你提供的href中已经列出了它,哈哈,它在“显式接口实现”下面。你真有趣。 - Erik Philips
显示剩余5条评论
2个回答

8

没问题,它是安全的。

看一下ConcurrentDictionary的参考源代码。方法IDictionary<TKey, TValue>.Add只是调用TryAdd并在键已存在时抛出异常。

接口成员的隐藏并不需要进行IL修改。可以通过C#中的显式接口实现来完成。这是通过省略方法的访问修饰符并在方法名前缀上接口名称来实现的:

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

做这个有各种各样的原因,可能你不想让具体的接口杂乱无章,或者你希望类的使用者在接口上使用的方法名称不够明确时更加明确。此外,它允许您为具有相同签名的不同接口上的方法提供单独的实现(我认为对于ConcurrentDictionary来说并不是真正的问题,但如果您需要在自己的类中使用,则可以具备该功能)。


2
我猜这是为了可以对某人说:“如果你知道自己在使用ConcurrentDictionary,那么应该使用TryAdd”,但当通过接口访问时仍然表现为IDictionary - Erik
2
如果你使用具体版本,人们会明白你的代码应该易读且使用TryAdd,并明确说明你的代码功能。 - Erik Philips
我认为这个讨论与C#接口的隐式实现和显式实现有关... - Mick

5
嗨,你正在玩一个危险的游戏。ConcurrentDictionary类的公共接口提供了线程安全的方法,你可以放心调用,知道它们表现良好。但Add()方法不是这样的方法,只有TryAdd()是。编译错误是因为Add()不是公共方法,Microsoft故意编写了一个显式接口实现版本,使该方法无法访问。否则,ConcurrentDictionary将实现IDictionary,他们是否应该实现该接口存在争议。但是,既成事实,他们已经实现了。

当然,你可以很容易地转换以访问Add()。但现在你感觉开始出现磨损。合理地说,他们能够实现Add()的唯一方法是在TryAdd()失败时抛出异常。如果基本操作失败时在工作线程上处理异常,祝你好运调试。

你绝对100%确定你能够处理工作线程上的异常吗?你有没有考虑过在catch子句中需要做什么,而不是考虑黑客IL呢?如果你考虑过,那么你的做法与TryAdd()返回false时所编写的代码有何不同?它并没有不同。


这并没有在生产代码中实现,只是一些小改动。我注意到了这种情况,并决定出于你所指定的确切原因使用具体类型。我觉得这有点奇怪,所以想问一下。 - dbarnes
嗯,一个难以调试的异常被视为一个功能而被点赞。我们在这里做什么呢?交叉着手指希望它不会发生吗? - Hans Passant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接