隐式泛型类型转换无法匹配重载方法签名

时间:2016-08-31 21:04:30

标签: c# generics implicit-conversion

我有一些课程如下:

public class RowBase { }

public class SpecificRow : RowBase { }

public class RowListItem<TRow> where TRow : RowBase { }

public class SpecificRowListItem : RowListItem<SpecificRow> { }

以下是一些方法:

public string GetName<TRow>(RowBase row) where TRow : RowBase { }

public string GetName<TRow>(RowListItem<TRow> item) where TRow : RowBase { }

我遇到的问题是RowListItem的子类无法匹配第二个重载的签名。以下是示例:

var foo = new SpecificRow();
var bar = new SpecificRowListItem();
var baz = new RowListItem<SpecificRow>();
string name;
name = GetName(foo); // invokes first overload as expected
name = GetName(baz); // invokes second overload as expected
name = GetName(bar); // does not compile
name = GetName((RowListItem<SpecificRow>)bar); // this alternative invokes the second overload
name = GetName<SpecificRow>(bar); // this alternative also invokes the second overload

编译器错误是

  

错误CS0311类型&#39; ConsoleApplication1.SpecificRowListItem&#39;不能用作类型参数&#39; TROW&#39;在通用类型或方法&#39; Program.GetName(TRow)&#39;。来自&#39; ConsoleApplication1.SpecificRowListItem&#39;没有隐式参考转换。到&#39; ConsoleApplication1.RowBase&#39;。

由于SpecificRowListItemRowListItem<TRow>的子类,TRow符合where TRow : RowBase约束,我希望编译器能够告诉它应该匹配提供参数作为该类的实例时的第二个重载。但是,编译器错误的文本表明它正在尝试匹配第一个重载(GetName(TRow))。我想了解为什么会这样,除了两个有效的替代方案之外,我还能做些什么来解决问题。我试过这个:

public string GetName<TItem, TRow>(TItem item)
    where TItem : RowListItem<TRow>
    where TRow : RowBase

除了丑陋之外,它给了我同样的问题(似乎与第一次重载相匹配)。

1 个答案:

答案 0 :(得分:1)

RowListItem<SpecificRow>RowListItem<BaseRow>没有关系,它并非来自它。

检查泛型中的协方差。这个答案可能会对您有所帮助:"out T" vs. "T" in Generics

工作示例:

  using System;

namespace CoVariance
{
    public class RowBase { }

    public class SpecificRow : RowBase { }

    public class RowListItem<TRow> : IInputSave<TRow> where TRow : RowBase { }

    public class SpecificRowListItem : RowListItem<SpecificRow> { }

    internal interface IInputSave<out TRow>
        where TRow : RowBase
    {
    }

    class Program
    {
        public static void Main(string[] args){

            var foo = new SpecificRow();
            var bar = new SpecificRowListItem();
            var baz = new RowListItem<SpecificRow>();
            string name;

            name = GetName(foo);
            Console.WriteLine(name); //oink
            name = GetName(baz);
            Console.WriteLine(name); //nested oink
            name = GetName(bar);
            Console.WriteLine(name); //nested oink
            name = GetName((RowListItem<SpecificRow>)bar);
            Console.WriteLine(name); //nested oink
            //name = GetName<SpecificRow>(bar); 

            Console.ReadKey();
        }

        public static string GetName(RowBase row)
        {
            return "oink";
        }

        public static string GetName(IInputSave<RowBase> item)
        {
            return "nested oink";
        }
    }
}