public class BaseContainer<T> : IEnumerable<T> { public void DoStuff(T item) { throw new NotImplementedException(); } public IEnumerator<T> GetEnumerator() { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { } } public class Container<T> : BaseContainer<T> { public void DoStuff(IEnumerable<T> collection) { } public void DoStuff <Tother>(IEnumerable<Tother> collection) where Tother: T { } }
前者定义了DoStuff(T项),后者用DoStuff< Tother>(IEnumerable< Tother>)重载它,专门用于解决缺少covariance/contravariance的C#(直到4听到).
这段代码
Container<string> c = new Container<string>(); c.DoStuff("Hello World");
遇到一个相当奇怪的编译错误.注意缺少< char>从方法调用.
The type ‘char’ cannot be used as type parameter ‘Tother’ in the generic type or method ‘Container.DoStuff(System.Collections.Generic.IEnumerable)’. There is no Boxing conversion from ‘char’ to ‘string’.
本质上,编译器试图将我对DoStuff(字符串)的调用阻塞到Container.DoStuff< char>(IEnumerable< char>)中,因为字符串实现了IEnumerable< char>,而不是使用BaseContainer.DoStuff(字符串).
我发现进行此编译的唯一方法是将DoStuff(T)添加到派生类
public class Container<T> : BaseContainer<T> { public new void DoStuff(T item) { base.DoStuff(item); } public void DoStuff(IEnumerable<T> collection) { } public void DoStuff <Tother>(IEnumerable<Tother> collection) where Tother: T { } }
为什么编译器试图将字符串堵塞为IEnumerable< char> 1)它知道它不能(假设存在编译错误)和2)它在基类中有一个编译好的方法?我是否误解了C#中的泛型或虚拟方法的东西?除了向Container添加新的DoStuff(T项)之外,还有其他修复方法吗?
解决方法
好的……我想我现在看到你的困惑了.您可能希望DoStuff(字符串)将参数保留为字符串,然后首先查找BaseClass方法列表以查找合适的签名,并且尝试将参数转换为其他类型时失败.
但它发生了反过来……相反,Container.DoStuff(字符串)去了,嗯“theres一个基类方法适合该法案,但我将转换为IEnumerable并对可用的内容进行心脏病发作在当前的班级而不是……
嗯……我肯定Jon或Marc能够在这一点上用特定的C#Spec段落来报道这个特殊的角落案例
原版的
两种方法都期望IEnumerable Collection
你正在传递一个单独的字符串.
编译器正在接受该字符串并继续
Ok,I have a string,Both methods
expect anIEnumerable<T>
,So I’ll
turn this string into an
IEnumerable<char>
… DoneRight,Check the first method…
hmmm… this class is a
Container<string>
but I have an
IEnumerable<char>
so that’s not right.Check the second method,hmmm…. I
have anIEnumerable<char>
but char
doesn’t implement string so that’s
not right either.
编译器错误
那么修复是什么,它完全取决于你想要实现的目标…以下两个都是有效的,基本上,你的类型用法在你的化身中是不正确的.
Container<char> c1 = new Container<char>(); c1.DoStuff("Hello World"); Container<string> c2 = new Container<string>(); c2.DoStuff(new List<string>() { "Hello","World" });