我在C#中遇到了一个问题,给我一个错误'无法从使用中推断出方法的类型参数'。如果我从非泛型列表派生通用列表,似乎编译器无法确定正确的接口:
代码:
public class SpecialItem : BaseItem
{
public string Title { get; set; }
}
public class BaseItem
{
public string Name { get; set; }
}
public class GenericList<T> : NongenericBaseList, IEnumerable<T>
where T: BaseItem
{
public new T this[int index]
{
get { return _items[index] as T; }
}
public new IEnumerator<T> GetEnumerator()
{
var iter = _items.GetEnumerator();
while (iter.MoveNext())
{
yield return iter.Current as T;
}
}
}
public class NongenericBaseList : IEnumerable<BaseItem>
{
protected List<BaseItem> _items;
public BaseItem this[int index]
{
get { return _items[index]; }
}
public IEnumerator<BaseItem> GetEnumerator()
{
return _items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
用法:
var genericList = new GenericList<SpecialItem>();
foreach (var item in genericList) // Uses IEnmerable<SpecialItem>, OK!
{
Console.WriteLine(item.Title);
}
var l = genericList.ToList(); // ERROR!
ForEarch获取正确的Enumerator(SpecialItem),但lambda不知道要使用什么(IEnumerable<BaseItem>
或IEnumerable<SpecialItem>
)。
怎么办?如何将IEnumerable<SpecialItem>
设置为“默认”界面?我不想像这样明确地对类型进行编码:
var l = genericList.ToList<SpecialItem>();
答案 0 :(得分:1)
首先:赞扬提供一个独立的例子!
您无法指定&#39;默认&#39;类型推断的接口。 ToList<T>
的参数类型无法解析,因为它不明确,类型同时实现IEnumerable<BaseItem>
和IEnumerable<SpecialItem>
,并且这两个版本都适用。
是否有可能完全删除课程NongenericBaseList
,而是使用GenericList<T>
?这可以解决你的问题;您可以使用GenericList<BaseItem>
代替NongenericBaseList
另一种选择是扭转继承;将NongenericBaseList
设为空并从GenericList<BaseItem>
派生。
答案 1 :(得分:0)
感谢Sriram Sakthivel,他引导我找到一个开销非常小的解决方案。为了清楚起见,我想确保:
IList<T>
,因此T out
不是一种选择。简而言之,以下代码必须编译而不会出错:
// Generic
var genericList = new GenericList<SpecialItem>();
foreach (var item in genericList)
{
Console.WriteLine(item.Title);
}
var l = genericList.ToList();
// Nongeneric
var nongenericList = genericList as NongenericBaseList;
foreach (var item in nongenericList)
{
Console.WriteLine(item.Name);
}
var nl = nongenericList.ToList();
我得出的结论是,对于上面的代码,这是不可能的(如果不是这样,请纠正我!)。循环工作正常,但泛型或非泛型列表不适用于.ToList()
或其他扩展方法,因为编译器无法推断出类型。
现在我使用了Sriram Sakthivel tipp,仅使用IEnumerable
而不使用<T>
。但即使您明确地写出类型,所有人都无法使用扩展方法。
我只是添加了一个属性,转换集合:
public class NongenericBaseList : IEnumerable // Without the T!
{
protected List<BaseItem> _items;
// The property
public IEnumerable<BaseItem> L
{
get { return this as IEnumerable<BaseItem>; }
}
public BaseItem this[int index]
{
get { return _items[index]; }
}
public IEnumerator<BaseItem> GetEnumerator()
{
return _items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
现在我可以输入:
var nl = nongenericList.L.ToList();
任何更好的解决方案都将不胜感激!