今天我遇到了一个令我困惑的编译问题。考虑这两个容器类。
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 item)
后者用 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(string)
的调用进入Container.DoStuff<char>(IEnumerable<char>)
因为string
工具 IEnumerable<char>
, 而不是使用 BaseContainer.DoStuff(string)
.
我发现进行此编译的唯一方法是添加 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# 中关于泛型或虚方法的东西?除了添加 new DoStuff(T item)
之外还有其他修复方法吗?至 Container
?
最佳答案
编辑
好的......我想我现在明白你的困惑了。您可能希望 DoStuff(string) 将参数保留为字符串,并首先遍历 BaseClass 方法列表以寻找合适的签名,如果失败则回退以尝试将参数转换为其他类型。
但事情恰恰相反……相反Container.DoStuff(string)
去了,嗯“那里有一个符合要求的基类方法,但我将转换为 IEnumerable 并且对当前类中可用的内容感到心脏病......
嗯...我确定此时 Jon 或 Marc 能够通过涵盖此特定极端情况的特定 C# 规范段落插话
原创
两种方法都需要一个 IEnumerable 集合
您正在传递一个单独的字符串。
编译器正在接受那个字符串,
Ok, I have a string, Both methods expect an
IEnumerable<T>
, So I'll turn this string into anIEnumerable<char>
... DoneRight, Check the first method... hmmm... this class is a
Container<string>
but I have anIEnumerable<char>
so that's not right.Check the second method, hmmm.... I have an
IEnumerable<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" });
关于c# - C#编译器的泛型、继承和失败的方法解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/922352/