将IEnumerable<>转换为IList<>

17

我正在使用Linq查询我的数据库并返回一个通用的IList。

无论我如何尝试,我都无法将IQueryable转换为IList。

这是我的代码。

我不能写得比这更简单了,但我不明白为什么它不起作用。

public  IList<IRegion> GetRegionList(string countryCode)
{
    var query = from c in Database.RegionDataSource
                where (c.CountryCode == countryCode)
                orderby c.Name
               select new {c.RegionCode, c.RegionName}; 

     return query.Cast<IRegion>().ToList(); 
}

这会返回一个数量正确但所有项都为空的列表。 请帮忙,我已经被这个问题困扰了几天。


1
这个问题和答案真的很好地阐述了鸭子类型的问题,以及 C#/Linq 的限制。 - Ron Klein
5个回答

17

你的select语句返回一个匿名类型:new {c.RegionCode, c.RegionName}

这不能转换为IRegion - 这基本上是鸭子类型,C#不支持。

你的linq语句应该返回一个实现IRegion的类型 - 然后你的代码就可以工作了。

但是它不应该运行 - Cast<IRegion>应该抛出运行时异常。

基本上:

// this isn't anonymous, and should cast
public class MyRegion : IRegion {
    public string RegionCode {get;set;}
    public string RegionName {get;set;}
}

public  IList<IRegion> GetRegionList(string countryCode)
{
    var query = from c in Database.RegionDataSource
                where (c.CountryCode == countryCode)
                orderby c.Name
               select new MyRegion {RegionCode = c.RegionCode, RegionName = c.RegionName}; 

     return query.Cast<IRegion>().ToList(); 
}

更新

如果底层的 Linq 类型实现了 IRegion,那么这将会变得更加简单:

public  IList<IRegion> GetRegionList(string countryCode)
{
    var query = 
        from region in Database.RegionDataSource
        where region.CountryCode == countryCode
        orderby region.Name
        select region; 

     return query.ToList(); 
}

1
现在你已经投影到具体类型中,所以不需要使用Cast<IRegion>() - Matt Kocaj
@cottsak:是的,他会的 - IList<T> 是不变的。 - Jon Skeet
我有一个由Linq自动生成的实现了IRegion接口的类Region。 当我使用它时,我得到了另一个错误信息:“查询中不允许显式构造实体类型'xxxx.LinqToSql.xxxx.Region'。” - nachid
@nachid - 啊哈,我想我们有一个解决方案!Database.RegionDataSource 返回 Region。要修复所有问题,你只需要以 select c 结尾即可。 - Keith

5

我很惊讶它没有完全失败 - 你试图将每个结果转换为IRegion,但你正在生成匿名类型的实例,这肯定不会实现IRegion

你是否有一个实现了IRegion的具体类型?


2

将匿名类型转换为IRegion是不可行的。您选择的是一个不会实现IRegion的匿名类型。是否有一种方法可以创建一个实现了IRegion接口的实例?


1

也许你需要类似这样的东西:

public  IList<IRegion> GetRegionList(string countryCode)
{
    var query = from c in Database.RegionDataSource
                where (c.CountryCode == countryCode)
                orderby c.Name
                select new Region() 
                    {
                        RegionCode = c.RegionCode, 
                        RegionName = c.RegionName
                    }; 

     return query.ToList(); 
}

我需要在返回查询结果之前以某种方式转换为IRegion。 编译器报错,无法将IList<Region>转换为IList<IRegion>。 - nachid

0
也许你需要类似这样的东西:
public  IList<IRegion> GetRegionList(string countryCode) 
{ 
    var query = from c in Database.RegionDataSource 
                where (c.CountryCode == countryCode) 
                orderby c.Name 
                select new Region()  
                    { 
                        RegionCode = c.RegionCode,  
                        RegionName = c.RegionName 
                    };  

     return query.ToList();  
}

我最终做了这个:public IList GetRegionList(string countryCode) { var query = from c in Database.RegionDataSource where (c.CountryCode == countryCode) orderby c.Name select c; return query.Cast().ToList(); }我很快就会回来告诉你。感谢您宝贵的帮助。 - nachid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接