Cam*_*ron 37 c# generics extension-methods .net-4.0 covariance
代码有点奇怪,所以忍受我(请记住这个场景确实出现在生产代码中).
说我有这个接口结构:
public interface IBase { }
public interface IChild : IBase { }
public interface IFoo<out T> where T : IBase { }
Run Code Online (Sandbox Code Playgroud)
这个扩展方法类围绕接口构建:
public static class FooExt
{
public static void DoSomething<TFoo>(this TFoo foo)
where TFoo : IFoo<IChild>
{
IFoo<IChild> bar = foo;
//foo.DoSomethingElse(); // Doesn't compile -- why not?
bar.DoSomethingElse(); // OK
DoSomethingElse(foo); // Also OK!
}
public static void DoSomethingElse(this IFoo<IBase> foo)
{
}
}
Run Code Online (Sandbox Code Playgroud)
为什么DoSomething编译中没有注释掉的行?编译器是非常高兴,让我分配foo到bar,这是同类型的通用约束,并呼吁该扩展方法来代替.没有扩展方法语法调用扩展方法也没问题.
任何人都可以确认这是一个错误或预期的行为吗?
谢谢!
仅供参考,这是编译错误(为清晰可读而删节的类型):
'TFoo'不包含'DoSomethingElse'的定义,最好的扩展方法重载'DoSomethingElse(IFoo)'有一些无效的参数
引用C#规范:
7.6.5.2扩展方法调用
在其中一个表单的方法调用(第7.5.5.1节)中
expr.标识符()
expr.标识符(args)
expr.标识符<typeargs>()
expr.标识符<typeargs>(args)
如果调用的正常处理找不到适用的方法,则尝试将该构造作为扩展方法调用进行处理.如果expr或任何args具有编译时类型dynamic,则扩展方法将不适用.
目标是找到最佳的类型名称C,以便可以进行相应的静态方法调用:
C .标识符(expr)
C .identifier(expr,args)
C .标识符<typeargs>(expr)
C .标识符<typeargs>(expr,args)
在以下情况下,扩展方法Ci.Mj符合条件:
· Ci是非泛型的非嵌套类
· Mj的名称是标识符
· 当如上所示作为静态方法应用于参数时,Mj是可访问且适用的
·从expr到Mj的第一个参数的类型存在隐式标识,引用或装箱转换.
由于DoSomethingElse(foo)编译但foo.DoSomethingElse()没有,好像在重载编译器故障而延期方法:隐式引用转换从存在foo到IFoo<IBase>.
你能在IFoo中定义DoSomethingElse吗?
public interface IFoo<out T> where T : IBase
{
void DoSomethingElse();
}
Run Code Online (Sandbox Code Playgroud)
UPDATE
也许你可以改变签名
public static void DoSomethingElse(this IFoo<IBase> foo)
=>
public static void DoSomethingElse<TFoo>(this TFoo foo)
where TFoo : IFoo<IChild>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2668 次 |
| 最近记录: |