jle*_*bke 2 linq generics interface
我必须在这里遗漏一些明显的东西.我不明白为什么这个linq查询结果的转换返回null而不是我正在请求的类型列表.
IList<IMyDataInterface> list = query.ToList() as IList<IMyDataInterface>;
Run Code Online (Sandbox Code Playgroud)
运行它的完整代码如下.这是我需要弥合的知识差距.我已经尝试过各种各样的演员阵容来让它发挥作用.我没有异常,只是一个空.值得注意的是,Linq查询将其结果选择为我的自定义"MyDataClass"的实例,该实现IMyDataInterface
class Program
{
static void Main(string[] args)
{
IMyFunctionalInterface myObject = new MyClass();
//myObject.Get() returns null for some reason...
IList<IMyDataInterface> list = myObject.Get();
Debug.Assert(list != null, "Cast List is null");
}
}
public interface IMyFunctionalInterface
{
IList<IMyDataInterface> Get();
}
public class MyClass : IMyFunctionalInterface
{
public IList<IMyDataInterface> Get()
{
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
var query = from n in names
where n.Contains("a")
select new MyDataClass
{
Name = n.ToString()
};
//There IS data in the query result
Debug.Assert(query != null, "result is null");
//but the cast here makes it return null
IList<IMyDataInterface> list = query.ToList() as IList<IMyDataInterface>;
return list;
}
}
public interface IMyDataInterface
{
string Name { get; set; }
}
public class MyDataClass : IMyDataInterface
{
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
Jay*_*uzi 13
这里的问题是协方差问题.
首先,你的例子有点太复杂了.我已经删除了一些绒毛.此外,我添加了一些解决问题的诊断.
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; }
}
Run Code Online (Sandbox Code Playgroud)
该程序的输出是:
System.Collections.Generic.List`1 [C]
请注意,我们正在尝试强制转换List<C>
为List<I>
在C#3.0中不起作用的内容.
在C#4.0中,你应该能够做到这一点,这要归功于通用接口上类型参数的新的共同和反差.
此外,您的原始问题询问IQueryable
但在此处不相关:您提供的查询表达式创建的IEnumerable<string>
不是IQueryable<string>
.
编辑:我想指出,使用as
运算符的"强制转换"在技术上不是强制转换,而是"类型转换".如果您使用了演员表,那么您将获得有用信息的例外.如果我改为:
var list = (IList<I>)query.ToList();
Run Code Online (Sandbox Code Playgroud)
我得到一个InvalidCastException
:
附加信息:无法转换'System.Collections.Generic.List 1[C]' to type 'System.Collections.Generic.IList
1 [I]' 类型的对象.
试试这个:
var query = from n in names
where n.Contains("a")
select new MyDataClass
{
Name = n.ToString()
} as IMyDataInterface;
Run Code Online (Sandbox Code Playgroud)
你的问题在于这一行:
IList<IMyDataInterface> list = query.ToList() as IList<IMyDataInterface>;
Run Code Online (Sandbox Code Playgroud)
这也可以写成:
List<MyDataClass> tmp = query.ToList();
IList<IMyDataInterface> list = tmp as IList<IMyDataInterface>;
Run Code Online (Sandbox Code Playgroud)
不幸的是,在C#中,as
运算符不能按照您希望的方式工作.的as
操作者只需连铸列表对象作为不同类型的列表; 它不会尝试通过列表并投射每个项目.要将列表转换为其他内容,您需要在其上调用Cast扩展方法.例如:
IList<IMyDataInterface> list = query.ToList().Cast<IMyDataInterface>();
Run Code Online (Sandbox Code Playgroud)
因此,您的选项是:将查询中的任何项目作为您想要的界面(我的第一个示例)投射,或者在执行查询后投射整个列表(我的第二个示例).
我建议前者.
归档时间: |
|
查看次数: |
12517 次 |
最近记录: |