讨论
正如一些答案所指出的那样,.Net 在问题范围内严格执行类型安全。Areinterpret_cast
本质上是一种不安全的操作,因此实现它的可能方法是通过反射或序列化,而这两者是相关的。
正如您在更新中提到的,可能的用途可能是 RPC 框架。无论如何,RPC 库通常都使用序列化/反射,并且有几个可用的:
所以,你可能不想自己写一个,也许。
如果您的课程Base
将使用公共属性,您可以使用AutoMapper:
class Base
{
public int Counter { get; set; }
// ...
}
...
AutoMapper.Mapper.CreateMap<Base, Foo>();
Foo foo = AutoMapper.Mapper.Map<Foo>(b);
Foo
根本不需要从哪里派生Base
。它只需要具有您有兴趣映射到的属性。但同样,您可能根本不需要两种类型 - 重新考虑架构可能是解决方案。
通常,不需要使用reinterpret_cast
, 通过一个干净的架构来很好地适应 .Net 框架中使用的模式。如果您仍然坚持使用类似的东西,这里有一个使用紧凑序列化库protobuf-net的解决方案。
序列化解决方案
你的课:
using System;
using System.IO;
using ProtoBuf;
using ProtoBuf.Meta;
[ProtoContract]
[ProtoInclude(3, typeof(Foo))]
class Base
{
[ProtoMember(1)]
protected int counter = 0;
public Base(int c) { counter = c; }
public Base() { }
}
[ProtoContract]
class Foo : Base
{
public int Counter { get { return counter; } }
}
和一个可运行的序列化-反序列化示例:
class Program
{
static void Main(string[] args)
{
Base b = new Base(33);
using (MemoryStream stream = new MemoryStream())
{
Serializer.Serialize<Base>(stream, b);
Console.WriteLine("Length: {0}", stream.Length);
stream.Seek(0, SeekOrigin.Begin);
Foo f=new Foo();
RuntimeTypeModel.Default.Deserialize(stream, f, typeof(Foo));
Console.WriteLine("Foo: {0}", f.Counter);
}
}
}
输出
Length: 2
Foo: 33
如果您不想在合约中声明派生类型,请参阅此示例...
如您所见,序列化非常紧凑。
如果要使用更多字段,可以尝试隐式序列化字段:
[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
泛型reinterpret_cast
绝对可以通过此序列化解决方案或直接通过反射来实现,但我目前不会投入时间。