Ste*_*ger 8 c# generics overloading
我对项目中遇到的问题感到困惑.我试图简化它以重现效果:
interface IBar { }
class Bar : IBar {}
interface IFoo<T> where T : IBar { }
class Foo<T> : IFoo<T> where T : IBar { }
class Class1
{
public void DoTheFoo<T>(T bar) where T : IBar
{}
public void DoTheFoo<T>(IFoo<T> foo) where T : IBar
{}
public void Test()
{
var bar = new Bar();
var foo = new Foo<Bar>();
DoTheFoo(bar); // works
DoTheFoo<Bar>(foo); // works
DoTheFoo((IFoo<Bar>)foo); // works
DoTheFoo(foo); // complains
}
}
Run Code Online (Sandbox Code Playgroud)
对我来说这看起来很好,但编译器在最后一次调用时抱怨,因为它试图DoTheFoo<T>(T bar)而不是DoTheFoo<T>(IFoo<T> foo)抱怨参数类型不适合.
DoTheFoo<T>(T bar),最后一次调用有效!DoTheFoo<T>(Foo<T> foo),它的工作原理,但我无法使用它在我们当前的代码中解决这个问题并不困难.但它是a)奇怪而且b)太糟糕了,我们不能拥有这两个重载方法.
是否存在解释此行为的通用规则?是否可以使它工作(除了给方法不同的名称)?
当与重载决策结合使用时,这只是类型推断的问题,而不是对你有利.只需明确指定类型参数即可轻松修复 - 无需强制转换:
DoTheFoo<Bar>(foo);
Run Code Online (Sandbox Code Playgroud)
通常我对过载采取相当不同的参数类型感到紧张.如果只是给方法赋予不同的名称,代码通常会更简单.除了其他任何东西,那么你的读者不需要尝试在类型推断的同时执行重载解析...
编辑:我认为问题是订购工作如下:
T = Foo<Bar>并获得第二种方法T = Bar.这两种方法都适用.T检查-和失败,因为有一个从没有引用转换Bar到IFoo.有一篇关于为什么语言是这样设计的Eric Lippert博客文章,我写的一篇关于它的博客文章,以及我写的关于一般的重载的文章.他们每个人可能会或可能不会帮助:)
编辑:抛开类型推断暂时,第一种方法更具体的原因是,在一种情况下,我们正在转换Foo<Bar>为Foo<Bar>,而在另一种情况下,我们正在转换Foo<Bar>为IFoo<Bar>.根据C#5规范的7.5.3.3节:
给定从表达式E转换为类型T1的隐式转换C1,以及从表达式E转换为类型T2的隐式转换C2,如果以下至少一个成立,则C1是比C2更好的转换: - E具有类型S并且存在从S到T1而不是从S到T2的身份转换 - ...
身份转换是从类型到自身,这是第一次重载的情况,但不适用于第二次.所以第一次转换更好.
| 归档时间: |
|
| 查看次数: |
1185 次 |
| 最近记录: |