C # InvalidCastException, хотя тот же базовый класс - PullRequest
1 голос
/ 13 июля 2009

Следующий код выдает InvalidCastException .

public static MachineProductCollection MachineProductsForMachine(
    MachineProductCollection MachineProductList, int MachineID)
{
    return (MachineProductCollection)
        MachineProductList.FindAll(c => c.MachineID == MachineID);
}

Это меня удивляет, поскольку MachineProductCollection - это просто общий список MachineProducts, который именно то, что должен вернуть FindAll (). Вот полный исходный код MachineProductCollection. Вы заметите, что это просто оболочка для List.

[Serializable]
public partial class MachineProductCollection :
        List<MachineProduct>
{
    public MachineProductCollection() { }
}

Я прибег к следующему, который в основном перебирает результат 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;
}

Документация гласит, что InvalidCastException генерируется, когда происходит сбой во время явного преобразования ссылки. Ссылочные преобразования - это преобразования из одного ссылочного типа в другой. Хотя они могут изменить тип ссылки, они никогда не изменят тип или значение цели конверсии. Преобразование объектов из одного типа в другой является частой причиной этого исключения.

Учитывая, что List является основой MachineProductCollection, действительно ли это InvalidCastException?

Ответы [ 2 ]

5 голосов
/ 13 июля 2009

Да, недопустимое исключение приведения правильное. Вы можете свободно приводить из производного класса в базовый класс, но вы не можете слепо приводить из базового класса к производному классу, если объект действительно не является экземпляром производного класса. По той же причине, по которой вы не можете сделать это:

object obj = new object();
string str = (string) obj;

Правильно? object является основой string, и вы не можете свободно разыгрывать от object до string. С другой стороны, это будет работать, поскольку obj действительно строка:

object obj = "foo";
string str = (string) obj;
1 голос
/ 13 июля 2009

Вы получаете InvalidCastException, потому что List<MachineProduct> не обязательно означает MachineProductCollection, хотя обратное очевидно очевидно.

Самым простым решением для возврата фактического MachineProductCollection было бы использование конструктора последовательности List<T>:

public static MachineProductCollection
    MachineProductForMachine(MachineProductCollection MachineProductList, int MachineID)
{
    List<MachineProduct> found =
        MachineProductList.FindAll(c => c.MachineID == MachineID))

    return new MachineProductCollection(found);
}

Однако, поскольку вы используете лямбда-выражения, я предполагаю, что у вас есть доступ к LINQ (через .NET 3.5 или LINQ Bridge ), что означает, что вы можете использовать метод расширения Where для пропуска промежуточный список:

public static MachineProductCollection
    MachineProductForMachine(MachineProductCollection MachineProductList, int MachineID)
{
    IEnumerable<MachineProduct> found =
        MachineProductList.Where(c => c.MachineID == MachineID))

    return new MachineProductCollection(found);
}

Тем не менее, вам может быть лучше просто вернуть IEnumerable<MachineProduct>, чем создавать собственный тип коллекции. Это, вероятно, сделает вашу жизнь проще, если вы не планируете добавлять специальную логику в MachineProductCollection. И в этом случае вы всегда можете просто написать методы расширения для IEnumerable<MachineProduct>, чтобы обеспечить эту логику. Просто некоторые вещи для рассмотрения ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...