C#InvalidCastException虽然是相同的基类

Ben*_*old 1 c# generics exception

以下代码抛出InvalidCastException.

public static MachineProductCollection MachineProductsForMachine(
    MachineProductCollection MachineProductList, int MachineID)
{
    return (MachineProductCollection)
        MachineProductList.FindAll(c => c.MachineID == MachineID);
}
Run Code Online (Sandbox Code Playgroud)

这让我感到惊讶,因为MachineProductCollection只是一个通用的MachineProducts列表,正是FindAll()应该返回的.这是完整的MachineProductCollection源代码.您将注意到它只是List的包装器.

[Serializable]
public partial class MachineProductCollection :
        List<MachineProduct>
{
    public MachineProductCollection() { }
}
Run Code Online (Sandbox Code Playgroud)

我使用了以下内容,它基本上循环遍历FindAll()类型为List的结果,并将每个项目添加到我的MachineProductCollection中.显然,我不喜欢所需的迭代.

public static MachineProductCollection
    MachineProductForMachine(MachineProductCollection
    MachineProductList, int MachineID)
{
    MachineProductCollection result =
        new MachineProductCollection();


    foreach (MachineProduct machineProduct in
        MachineProductList.FindAll(c => c.MachineID == MachineID))
    {
        result.Add(machineProduct);
    }

    return result;
}
Run Code Online (Sandbox Code Playgroud)

文档指出在显式引用转换期间发生故障时抛出InvalidCastException.参考转化是从一种参考类型到另一种参考类型的转换.虽然它们可能会更改引用的类型,但它们永远不会更改转换目标的类型或值.将对象从一种类型转换为另一种类型是此异常的常见原因.

考虑List是MachineProductCollection的基础,这真的应该是InvalidCastException吗?

Joh*_*ica 5

是的,无效的强制转换异常是正确的.您可以从派生类自由地转换为基类,但是您不能盲目地从基类转换为派生类,除非该对象确实派生类的实例.这是你不能这样做的原因:

object obj = new object();
string str = (string) obj;
Run Code Online (Sandbox Code Playgroud)

对?objectstring基础,你不能自由地投射objectstring.另一方面,这将起作用,因为obj它确实是一个字符串:

object obj = "foo";
string str = (string) obj;
Run Code Online (Sandbox Code Playgroud)