Разные типы в массиве, как узнать, к чему их приводить, когда вынимают их из массива? - PullRequest
4 голосов
/ 29 июня 2011

Предположим универсальный Список типа Пакет , содержащий пользовательские классы, расширяющие Пакет , например LoginPacket или ChatPacket .

Допустим, я положил их в список. Когда я достану их, наиболее «конкретным» типом будет Packet . Я хочу привести их к более конкретным типам, однако, обратно в их исходный LoginPacket или ChatPacket или обратно в прежние типы.

Вопрос: Как я могу это сделать?

Ссылка: Как программно преобразовать объект во время выполнения?

Итак ... похоже, что если эти пользовательские классы имеют общий интерфейс, это решит проблему приведения? Но если так, мои классы не могут все иметь один интерфейс. Мне нужно строить интерфейсы на интерфейсах и классы на классах. Итак ... как бы я это сделал? Извините, если этот вопрос не так точен. Не уверен, как сформулировать мой точный вопрос.

Ответы [ 2 ]

5 голосов
/ 29 июня 2011

Вы можете иметь целый длинный список if / else или переключателя

if (item is ChatPacket)
{
    // cast
}
else if (...)
{
    // cast
}
else ...

Однако это может стать громоздким.

Возможно, вы захотите вернуться к дизайну вашего класса. Имея List<Packet>, вы фактически заявляете , что вас не волнует разница между производными дочерними элементами , по крайней мере, с точки зрения их уникальных API.

Другими словами, если ваш дизайн

class Packet { public void Foo() { } }
class ChatPacket : Packet { public void Bar() { } }

Вы говорите, что заботитесь только о возможности доступа Foo().

Если вы действительно заботитесь о различиях, возможно, вы можете выразить эти различия с помощью полиморфизма с помощью абстрактных или виртуальных методов в базовом и переопределенном поведении детей. Поэтому у вас все еще есть коллекция базовых классов, но вы по-прежнему получаете пользовательское поведение, указанное каждым дочерним классом.

class Packet { public virtual void Foo() { } }
class ChatPacket : Packet { public override void Foo() { } }

Здесь вы звоните, просто позвоните Foo(). Не требуется литье.

2 голосов
/ 29 июня 2011

Вы можете сделать что-то вроде этого:

if (myPacket is LoginPacket) {
    // Do LoginPacket stuff
}

else if (myPacket is ChatPacket) {
    // Do ChatPacket stuff
}

Когда вы знаете, правильный ли это тип, вы можете разыграть его, используя ключевое слово as

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