我试图理解为什么这个演员不起作用:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CastTest {
class Foo {}
// I want to use this kind of like a typedef, to avoid writing List<Foo> everywhere.
class FooList : List<Foo> {}
class Program {
static void Main(string[] args) {
FooList list = (FooList) Program.GetFooList();
}
// Suppose this is some library method, and i don't have control over the return type
static List<Foo> GetFooList() {
return new List<Foo>();
}
}
}
这会生成运行时错误:
InvalidCastException:无法将类型为'System.Collections.Generic.List`1 [CastTest.Foo]'的对象强制转换为'CastTest.FooList'。
任何人都可以解释为什么这不起作用,以及我是否可以以某种方式解决这个问题?
答案 0 :(得分:7)
仅仅因为您的FooList是List而不会使List成为FooList。
答案 1 :(得分:5)
您无法自动从父类强制转换为派生类:只是因为您尝试投射的对象是List<Foo>
并不一定会使其成为FooList
。
退房:
您可以编写一个将List<Foo>
转换为FooList
的运算符,也许可以使用AddRange
填充值,例如:
class FooList
{
public explicit operator FooList(List<Foo> arg)
{
FooList result = new FooList();
result.AddRange(arg);
return result;
}
}
此外,最好只使用using
别名:
http://msdn.microsoft.com/en-us/library/sf0df423(v=vs.80).aspx
using FooList = List<Foo>;
这样你实际上并没有传递不必要的派生类。
答案 2 :(得分:4)
此方法:
static List<Foo> GetFooList() {
return new List<Foo>();
}
...不会返回FooList
。您的代码实际上是这样的:
FooList list = (FooList) new List<Foo>();
这根本不起作用。它无效:
string x = (string) new object();
你不会指望这样,你呢?那你的FooList
版本为什么会起作用?
答案 3 :(得分:2)
最接近C#的typedef称为使用别名指令:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CastTest {
using FooList = List<Foo>;
class Foo {}
class Program {
static void Main(string[] args) {
FooList list = Program.GetFooList();
}
// Suppose this is some library method, and i don't have control over the return type
static List<Foo> GetFooList() {
return new List<Foo>();
}
}
}
您创建了派生类FooList
,但这会创建别名FooList
。它与List<Foo>
不兼容, List<Foo>
。
答案 4 :(得分:2)
因为并非所有List都是FooList。例如,我可以:
public class AnotherFooList : List<Foo>
{
public object AdditionalPropery {get; set; }
}
它也继承自List,但与FooList不同,FooList与它不同。
答案 5 :(得分:1)
由于您知道FooList
实际上只是List<Foo>
的另一个名称,因此它可能看起来很奇怪。但鉴于FooList
可能包含成员本身,编译器不应允许强制转换变得明确。想象一下,您稍后会在Bar()
上介绍一种方法(FooList
)。 List<Foo>
上不存在此方法,如果允许赋值(或强制转换),则类型系统将会中断。
答案 6 :(得分:1)
你不能上升;但你可以创建一个新的FooList实例及其内容
class Foo { }
// I want to use this kind of like a typedef, to avoid writing List<Foo> everywhere.
class FooList : List<Foo> {}
class Program
{
static void Main(string[] args)
{
FooList l = new FooList();
l.AddRange(GetFooList().Select(foo => foo));
Console.ReadLine();
}
// Suppose this is some library method, and i don't have control over the return type
static List<Foo> GetFooList()
{
return new List<Foo>();
}
}