这是做不到的。
备选方案1
然而,你可以通过使用两个列表 (List<MyMessageType1>
和 List<MyMessageType2>
) 来模拟这些东西。
然后,你可以构造一个超级索引 (可能只是另一个 int 数组 (longs?) ),使得能够(间接)像处理一个列表一样地处理其中的项。
你可能想要优化此索引 (运行长度编码: 仅存储后备数组切换的索引: 当迭代已知为一个后备数组连续子范围时,这也将极大地帮助)
列表在内部使用阵列存储,所以:
- 你不会遭遇装箱问题
- 快速随机访问
- 使用 list.ForEach 快速迭代
备选方案2
查看 StructLayout 特性,并通过进行所有操作来模拟 Union。如果你真的准备好了,请使用unsafe {}
代码块(并启用 / unsafe 编译选项)... 然而,如果非常重要,认真考虑 P/Invoke C DLL 或使用 C++/CLI。
备选方案3 (新增)
因为我真的很喜欢 Marc Gravell 指出的可以使用我提到的 StructLayout,来定位 .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
结构中添加一个字段,但根据负载的不同,其他方法可能更加高效(空间/时间)。
我的两分钱
噢,我从未真正这样做,因为它似乎过于复杂了。我假设你有一个有效的理由来优化这个。
另外,如果你在看完我的回答之后才问这个问题(昨天: 应该使用结构体还是类来表示Lat/Lng坐标?),我将会怀疑这是一种过早的优化。