c# - C#编译器的泛型、继承和失败的方法解析

标签 c# generics compilation

今天我遇到了一个令我困惑的编译问题。考虑这两个容器类。

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 an IEnumerable<char>... Done

Right, 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 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/

相关文章:

java - 为什么这个带有绑定(bind)的泛型方法可以返回任何类型?

apache-flex - 是否确实需要旧版本的flex SDK?

c# DataSet 无法进行此更改,因为对关系 XXX 强制实现约束,并且更改此值将限制子行

c# - 将 Base64 图像从 View 发送到 ASP.NET Controller

c# - 允许 C# 插件在应用程序 Hook 上注册

c# - 使用 C# 和 WPF 在 Windows 上防止屏幕捕获

java - 为什么java.lang.Object不能转换成T?

java - 使用泛型调用父类的 super()

Java 编译错误缺少 return 语句。需要澄清

计算已编译 C 程序的代码指标