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

2024-03-09

我必须在这里遗漏一些明显的东西。我不明白为什么 linq 查询结果的转换返回 null 而不是我请求的类型化列表。

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; }
}

这里的问题是之一协方差.

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

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.IList1[I]'.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linq - 将 IQueryable 转换为 IList 返回 null - 为什么? 的相关文章

随机推荐