C#中的Linq查询和转换

Gil*_*and 2 c# linq casting predicate

我有一个名为 的类BaseViewModel,以及从它继承的多个类。

我有一个List<BaseViewModel>包含所有子类,而不是单个BaseViewModel.

现在,我想提取特定类型的所有类,比如 my DateViewModel,从List<BaseViewModel>

现在我正在这样做,这会抛出一个InvalidCastException

CustomFieldViewModels是 myList<BaseViewModel>它有一个ControlType枚举,我用它来识别所有“孩子”。

public List<DateViewModel> DateCustomViewModels
{
    get
    {
        return (List<DateViewModel>)CustomFieldViewModels
            .Where(x => x.ControlType == CustomFieldControlValueType.Date);
    }
}
Run Code Online (Sandbox Code Playgroud)

我对 Linq 相当陌生,我不确定我做错了什么。

我也很确定执行 aforeach并填充 aList<DateViewModel>在性能方面没有那么好,也不是很干净。

据我了解,.Where它将返回一个List我所要求的,带有过滤器(这里是我的枚举)。我不明白为什么会出现问题,因为我所有的孩子都继承自父类,而且我没有在过滤中使用特定于孩子的元素。此外,即使主列表的类型是 Base,它的元素都不属于 Base 类型,因此首先不应该进行任何转换。

我觉得我错过了一些非常明显的东西,但我看不到它,非常欢迎任何帮助。

如果您提供答案,如果您能给出一个简短的解释而不仅仅是复制粘贴代码,我们将不胜感激:)

编辑:为了展示我最终做了什么,我选择了各种答案的混合,因为我不需要列表,但我仍然需要类型。

public IEnumerable<DateControlViewModel> DateCustomViewModels
{
    get
    {
        return CustomFieldControlViewModels.OfType<DateControlViewModel>();
    }
}
Run Code Online (Sandbox Code Playgroud)

hai*_*770 5

您需要使用OfType()

public List<DateViewModel> DateCustomViewModels
{
    get
    {
        return CustomFieldViewModels.OfType<DateViewModel>().ToList()
    }
}
Run Code Online (Sandbox Code Playgroud)

据我了解, .Where 将返回一个包含我所要求的任何内容的列表,并带有一个过滤器(这里是我的枚举)

不,它会返回IEnumerable<BaseViewModel>。您在 中指定的条件Where()不会更改返回类型,它仅指定BaseViewModel将包含哪些对象。

我不明白为什么会出现问题,因为我所有的孩子都继承自父类,而且我没有在过滤中使用特定于孩子的元素。

即使DateViewModel继承自BaseViewModel,您也不能显式地强制转换为List<DateViewModel>List<BaseViewModel>因为它List<T>不变的

此外,即使主列表的类型是 Base,它的元素都不属于 Base 类型,因此首先不应该进行任何转换。

你是对的,不需要铸造。使用OfType<DateViewModel>()它只会返回DateViewModel. 此外,返回的集合现在是IEnumerable<DateViewModel>(不再是List<BaseViewModel>)并且编译器可以验证它是否与DateCustomViewModels属性的返回类型兼容。

MSDN