隐式泛型类型转换无法匹配重载的方法签名
本文关键字:重载 方法 泛型 类型转换 | 更新日期: 2023-09-27 18:05:07
我有一些类如下:
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 类型"控制台应用程序 1.特定行列表项"不能用作泛型类型或方法"程序.获取名称(TRow("中的类型参数"TRow"。没有从"ConsoleApplication1.SpecificRowListItem"到"ConsoleApplication1.RowBase"的隐式引用转换。
由于 SpecificRowListItem
是具有满足where TRow : RowBase
约束的TRow
的 RowListItem<TRow>
子类,因此我希望编译器能够在提供参数作为该类的实例时判断它应该与第二个重载匹配。 但是,编译器错误的文本指示它正在尝试匹配第一个重载 (GetName(TRow)
(。 我想了解为什么会这样,以及除了两种有效的替代方案之外,我是否可以做些什么来解决问题。 我试过这个:
public string GetName<TItem, TRow>(TItem item)
where TItem : RowListItem<TRow>
where TRow : RowBase
除了丑陋之外,它还给了我同样的问题(似乎与第一次重载相匹配(。
RowListItem<SpecificRow>
与RowListItem<BaseRow>
没有关系,它不是从它派生出来的。
查看泛型中的协方差。 这个答案可能会帮助你: 泛型中的"out T"与"T">
工作示例:
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";
}
}
}