Это не может быть сделано.
Альтернатива 1
Однако вы можете эмулировать вещи, используя два списка (List<MyMessageType1>
и List<MyMessageType2>
).
Затем вы создаете один супериндекс (возможно, просто другой массив целых чисел (длинных?)), Чтобы можно было (косвенно) адресовать элемент, как если бы он был одним списком.
Возможно, вы захотите оптимизировать индекс (кодирование длины выполнения: хранить только индексы, на которых переключается резервный массив: это также очень поможет при итерации поддиапазона, который, как известно, является смежным в одном из резервных массивов)
Списки используют Array storage для внутреннего использования, поэтому
- вы не получите бокс
- быстрый произвольный доступ
- сверкающая итерация со списком. ForEach
Альтернатива 2
Посмотрите на атрибут StructLayout и каким-то образом эмулируйте Союз, выполняя все манипуляции. Если вы действительно готовы испачкать руки, добавьте блоки unsafe {}
(и скомпилируйте с / unsafe) ... однако, серьезно подумайте о P / Invoke C DLL или используйте C ++ / CLI, если это имеет значение что много
Альтернатива 3 (добавлено)
Поскольку мне действительно понравился тот факт, что Марк Гравелл указал, что вы можете использовать упомянутый мной StructLayout, чтобы точно определить все три члена структуры union .NET с одинаковым смещением; Я думал, что сделаю еще один шаг и посмотрю, смогу ли я сделать это намного более дырявым прозрачным еще. Это очень близко к прозрачности:
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace LeakyAbstractions
{
struct TypeA {}
struct TypeB {}
struct TypeC {}
[StructLayout(LayoutKind.Explicit)] internal struct AnyMessage {
[FieldOffset(0)] public TypeA A;
[FieldOffset(0)] public TypeB B;
[FieldOffset(0)] public TypeC C;
AnyMessage(TypeA a) { A = a; }
AnyMessage(TypeB b) { B = b; }
AnyMessage(TypeC c) { C = c; }
public static implicit operator TypeA(AnyMessage msg) { return msg.A; }
public static implicit operator TypeB(AnyMessage msg) { return msg.B; }
public static implicit operator TypeC(AnyMessage msg) { return msg.C; }
public static implicit operator AnyMessage(TypeA a) { return a; }
public static implicit operator AnyMessage(TypeB b) { return b; }
public static implicit operator AnyMessage(TypeC c) { return c; }
}
public class X
{
public static void Main(string[] s)
{
var anyMessages = new List<AnyMessage> {
new TypeA(),
new TypeB(),
new TypeC(),
};
TypeA a = anyMessages[0];
TypeB b = anyMessages[1];
TypeC c = anyMessages[2];
anyMessages.Add(a);
anyMessages.Add(b);
anyMessages.Add(c);
}
}
}
Я оставлю вам задачу различения этого варианта бедных мужчин как упражнение. Самый простой способ - добавить поле в структуру AnyMessage
, но в зависимости от полезной нагрузки другие стратегии могут быть гораздо более эффективными (пространство / время).
Мои $ 0,02
О, я бы никогда этого не сделал, потому что это кажется слишком сложным. Я полагаю, у вас есть веская причина для оптимизации этого
PS. Если вы спросите об этом после прочтения моего ответа здесь (вчера: Должен ли я использовать структуру или класс для представления координат широты / долготы? ), я собираюсь оценить это преждевременно оптимизация