讨论
正如一些答案所指出的那样,在问题的范围内,.Net严格执行类型安全。使用reinterpret_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 Framework中使用的模式。如果您仍然坚持要使用类似于此的东西,那么这里有一个使用紧凑型序列化库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
是可能的,但目前我不会花时间去投资。
C#
比C++
更加类型安全。 - Hamlet Hakobyanreinterpret_cast
是本质上不安全的,因为你几乎无法确定它是否正确工作。通过使用序列化(如果需要紧凑的序列化,则使用二进制),你可以获得对故障的细粒度控制,特别是部分故障。正如其他评论者所指出的那样,.Net 类型系统应该是安全的 :) - Dmitry Ledentsov