C#无法转换自综合<Base> 要类型<Derived>
-
10-07-2019 - |
题
我最近遇到麻烦的时候,试图AddRange(综合),一个列表。可能是一个经典的问题,但是我真的不得到它。
我明白,方法期待一个列表中的参数不满意的一个列表,因为他们可能尝试增加一个基本列表,这显然是不可能的。
但如果我得到这正确的,因为IEnumerables自己无法改变的,它应该来工作,在这种情况。
代码我认为是这样的:
class Foo
{
}
class Bar : Foo
{
}
class FooCol
{
private List<Foo> m_Foos = new List<Foo> ();
public void AddRange1(IEnumerable<Foo> foos)
{
m_Foos.AddRange (foos); // does work
}
public void AddRange2<T>(IEnumerable<T> foos) where T : Foo
{
m_Foos.AddRange (foos); // does not work
}
}
class Program
{
static void Main(string[] args)
{
FooCol fooCol = new FooCol ();
List<Foo> foos = new List<Foo> ();
List<Bar> bars = new List<Bar> ();
fooCol.AddRange1 (foos); // does work
fooCol.AddRange1 (bars); // does not work
fooCol.AddRange2 (foos); // does work
fooCol.AddRange2 (bars); // does work
}
}
我试图通过一个提示来编译器在AddRange2方法,但是,这只是转移问题的周围。
是我的思维方式有缺陷的?这一限制语言,或是通过设计?
请参考,支持这种行动加入Java1.5,因此也许它会被添加到C#在某一点在未来,太...?
解决方案
这是协,并将其固定在C#4.0/.净4.0.现在,一般的选择是最好的答案(对 IEnumerable<T>
- 不 IList<T>
等等).
但在通用的方法,则必须考虑的 T
.你也可以使用 Cast<T>
或 OfType<T>
与皇宫实现类似的东西。
其他提示
在C#3.0则可以使用“铸”扩展方法。如果您导入System.Linq的,然后使用此代码:
public void AddRange2<T>(IEnumerable<T> foos) where T : Foo
{
m_Foos.AddRange (foos.Cast<Foo>());
}
然后,它应该为你工作。
有替代方法是用扩展方法:
public static IEnumerable<TBase> ToBaseEnumerable<TBase, TDerived>( this IEnumerable<TDerived> items ) where TDerived : TBase {
foreach( var item in items ) {
yield return item;
}
}
...
IEnumerable<Employee> employees = GetEmployees(); //Emplyoee derives from Person
DoSomethingWithPersons( employees.ToBaseEnumerable<Person, Employee>() );
但 “<人,雇员>” 是有点笨拙:/
当然,浇注溶液可能产生类转换异常。 谁张贴周围的枚举推广工作的人说,这是尴尬。 我想出了一个解决方案,它是只有一半的尴尬,不知道我是否会使用它:
public static class UpTo<T>
{
public static IEnumerable<T> From<F>(IEnumerable<F> source) where F:T
{
// this cast is guaranteed to work
return source.Select(f => (T) f);
}
}
用法:
IEnumerable的哺乳动物=高达<哺乳动物>。从(kennel.Dogs)
不隶属于 StackOverflow