这里的问题是之一协方差.
首先,你的例子有点太复杂了。我已经去掉了一些绒毛。另外,我还添加了一些诊断来阐明问题。
class Program
{
static void Main(string[] args)
{
var names = new[] { "Tom", "Dick", "Harry", "Mary", "Jay" };
var query = from n in names
select new C
{
S = n
};
//There IS data in the query result
Debug.Assert(query != null, "result is null");
//but the conversion here makes it return null
var list = query.ToList() as IList<I>;
Console.WriteLine(query.ToList().GetType());
// this assert fires.
Debug.Assert(list != null, "Cast List is null");
}
}
interface I
{
string S { get; set; }
}
class C : I
{
public string S { get; set; }
}
该程序的输出是:
System.Collections.Generic.List`1[C]
请注意,我们正在尝试投射List<C>
to List<I>
这在 C# 3.0 中不起作用。
在 C# 4.0 中,您应该能够做到这一点,这要归功于泛型接口上类型参数的新协变和逆变。
另外,你原来的问题是关于IQueryable
但这与这里无关:您提供的查询表达式创建一个IEnumerable<string>
not an IQueryable<string>
.
EDIT:我想指出你的“演员”使用as
从技术上讲,运算符不是强制转换,而是“类型转换”。如果您使用了强制转换,您将会得到一个带有有用信息的异常。如果我更改为:
var list = (IList<I>)query.ToList();
我得到一个InvalidCastException
with:
Additional information: Unable to cast object of type 'System.Collections.Generic.List1[C]' to type 'System.Collections.Generic.IList
1[I]'.