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

我今天碰到了编辑问题,这让我感到困惑.考虑这两个容器类.
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 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" });

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...