C#中的方法重载决策和通用/逆变接口

Ste*_*han 7 c# overloading contravariance overload-resolution

我认为我的问题最好用我的类/接口层次结构的代码片段来解释:

public interface ITransform<D> // or <in D> --> seems to make no difference here
{
    void Transform(D data);
}

interface ISelection {}
interface IValue : ISelection {}

public interface IEditor : ITransform<IValue> {}
public interface ISelector : IEditor, ITransform<ISelection> {}

class Value : IValue { ... }
class Editor : IEditor { ... }              // implements ITransform<IValue>
class Selector : Editor, ISelector { ... }  // implements ITransform<ISelection>

Value v = new Value();
Selector s1 = new Selector();
ISelector s2 = s1;

s1.Transform(v); // resolves to ITransform<ISelection> --> WHY?
s2.Transform(v); // resolves to ITransform<IValue>     --> OK
Run Code Online (Sandbox Code Playgroud)

问题1:为什么在第二种情况下s1.Transform(v)解决ITransform<ISelection>而不是解决ITransform<IValue>

问题2:对于问题1,如果ITransform<D>或者似乎没有区别<in D>.但是你<in D>在我的类/接口层次结构中看到任何其他问题吗?我有点怀疑,因为ISelector它的工具ITransform<IValue>ITransform<ISelection>.可能会有逆转导致这里的任何问题,因为IValue继承ISelection

编辑 只是为了让你知道:我目前正在使用Silverlight 4,但我认为这是一般的C#行为.

mak*_*aka 2

您的 Selector 类实现了 ITransform 接口,这意味着您必须包含处理 Transform(ISelection) 的代码。您的类还可以处理 Transform(IValue),但只能通过从 Editor 类继承的方法来处理。

\n\n

它选择 ISelection 变体的原因是因为这是在 Selector 类中显式声明的变体。要选择 Transform(IValue),编译器必须假设您宁愿处理来自基类(编辑器)的调用。

\n\n

编辑:C# 规范的一些背景。

\n\n
\n

这些上下文中的每一个都以自己独特的方式定义候选函数成员集和参数列表,如上面列出的部分中详细描述的。例如,方法调用的候选集不包括标记为 override (\xc2\xa77.4) 的方法,并且如果派生类中的任何方法适用,则基类中的方法不是候选方法(\xc2\xa77.6.5.1)。

\n
\n