代码之家  ›  专栏  ›  技术社区  ›  jlembke

Linq-将IQueryable转换为IList返回null-为什么?

  •  2
  • jlembke  · 技术社区  · 16 年前

    IList<IMyDataInterface> list = query.ToList() as IList<IMyDataInterface>;
    

    下面是运行此操作的完整代码。这是我需要弥合的知识鸿沟。我尝试了各种类型的演员阵容排列,以使其发挥作用。我没有例外,只有一个空值。值得注意的是,Linq查询将其结果选择到实现IMyDataInterface的自定义“MyDataClass”实例中

    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; }
    }
    
    2 回复  |  直到 16 年前
        1
  •  13
  •   Jay Bazuzi Buck Hodges    15 年前

    这里的问题是其中之一 .

    首先,你的例子有点太复杂了。我去掉了一些绒毛。此外,我还添加了一些诊断说明问题。

    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> List<I> 这在C#3.0中不起作用。

    还有,你最初的问题是关于 IQueryable IEnumerable<string> 不是 IQueryable<string> .

    编辑 as 运算符在技术上不是强制转换,而是“类型转换”。如果您使用了强制转换,您将得到一个包含有用信息的异常。如果我改为:

        var list = (IList<I>)query.ToList();
    

    我得到一份工作 InvalidCastException 与:

    Additional information: Unable to cast object of type 'System.Collections.Generic.List1[C]' to type 'System.Collections.Generic.IList1[I]'.
    
        2
  •  5
  •   Randolpho    16 年前

    试试这个:

    var query = from n in names
                where n.Contains("a")
                select new MyDataClass
                {
                  Name = n.ToString()
                } as IMyDataInterface;
    

    您的问题在这一行:

    IList<IMyDataInterface> list = query.ToList() as IList<IMyDataInterface>;
    

    这也可以写成:

    List<MyDataClass> tmp = query.ToList();
    IList<IMyDataInterface> list = tmp as IList<IMyDataInterface>;
    

    as 操作员未按您希望的方式工作。这个

    IList<IMyDataInterface> list = query.ToList().Cast<IMyDataInterface>();
    

    因此,您的选项是:将查询中的任何项转换为所需的接口(我的第一个示例),或在执行查询后转换整个列表(我的第二个示例)。