C ++ equivalent reinterpret_cast in C #

Interestingly, the C ++ equivalent of reinterpret_cast in C #!?

Here is my example:

 class Base { protected int counter = 0; } class Foo : Base { public int Counter { get { return counter; } } } Base b = new Base(); Foo f = b as Foo; // f will be null 

I have no objection why f will be empty, as it should be. But if it was C ++, I could write Foo f = reinterpret_cast<Foo>(b); and get what I wanted. What can I do to achieve the same result in C #?

PS. I assume Base and Foo match the data.

[UPDATE]

Here is a simple scenario where reinterpret_cast can be useful:

Consider writing the XXX-RPC library in which you have no control over the incoming parameters and the signature of the services to call. It is assumed that your library will call the requested service with the specified parameters. If C # supported reinterpret_cast I could just reinterpret_cast given parameters to the expected ones and call the service.

+10
c # reinterpret-cast
source share
7 answers

discussion

As some answers point out, .Net strictly adheres to type safety within the scope of the question. reinterpret_cast will be an unsafe operation, so the possible ways to implement it are either reflection or serialization, while both are interconnected.

As you mentioned in the update, a possible use could be an RPC structure. RPC libraries usually use serialization / reflection anyway, and there are a few useful ones:

so you may not want to write it yourself.

If your Base class will use public properties, you can use AutoMapper :

 class Base { public int Counter { get; set; } // ... } 

...

 AutoMapper.Mapper.CreateMap<Base, Foo>(); Foo foo = AutoMapper.Mapper.Map<Foo>(b); 

Where Foo does not need to be extracted from Base . It just needs to have the property that you are interested in displaying. But then again, you may not need two types at all - rethinking the architecture may be the solution.

Typically, there is no need to use reinterpret_cast as a clean architecture that fits well with the templates used in the .Net Framework. If you still insist on having something like this, here is a solution using the compact protobuf-net serialization library.

serialization solution

Your classes:

 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; } } } 

and a working example of serialization-deserialization:

 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); } } } 

Output

 Length: 2 Foo: 33 

If you do not want to declare derived types in your contract, see this example ...

As you can see, serialization is extremely compact.

If you want to use more fields, you can try implicit field serialization:

 [ProtoContract(ImplicitFields = ImplicitFields.AllFields)] 

The universal reinterpret_cast , of course, can be implemented either using this serialization solution or directly using reflection, but I would not waste time at the moment.

+6
source share

It works. And yes, it is as evil and as amazing as you can imagine.

 static unsafe TDest ReinterpretCast<TSource, TDest>(TSource source) { var sourceRef = __makeref(source); var dest = default(TDest); var destRef = __makeref(dest); *(IntPtr*)&destRef = *(IntPtr*)&sourceRef; return __refvalue(destRef, TDest); } 

It should be noted that if you use T[] to and U[] :

  • If T greater than U , border checking will not allow you to access elements of U that precede the original length of T[]
  • If T less than U , border checking will let you read the last element (in fact, its buffer overflow vulnerability).
+7
source share

You might be able to achieve similar behavior with unsafe and void* blocks in C #:

 unsafe static TResult ReinterpretCast<TOriginal, TResult>(this TOriginal original) where TOriginal : struct where TResult : struct { return *(TResult*)(void*)&original; } 

Using:

 Bar b = new Bar(); Foo f = b.ReinterpretCast<Foo>(); f = ReinterpretCast<Foo>(b); // this works as well 

Not tested.

Structural constraints reset the point of your question, I think, but they are necessary because classes are managed by GC, so you are not allowed to have pointers to them.

+2
source share

C # does not have a hole in the type system that would allow you to do this. He knows what these things are and will not allow you to use another type. The reasons for this are pretty obvious. What happens when you add a field to Foo?

If you need a Foo type, you need to create a Foo type. What might be a better route is to create a constructor of type Foo that takes a Base as parameter.

+1
source share

This is my "implementation"

 [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public unsafe static TResult ReinterpretCast<TOriginal, TResult>(/*this*/ TOriginal orig) //refember ReferenceTypes are references to the CLRHeader //where TOriginal : struct //where TResult : struct { return Read<TResult>(AddressOf(orig)); } 

Make sure you know what you are doing when you call it, especially with reference types.

+1
source share

Since b is just a Base instance, you can never pass it to a non-empty Foo instance. Perhaps an interface might better suit your needs?

0
source share

If Foo and Bar were structs, you could do

  [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)] public class MyFooBarHelper { [System.Runtime.InteropServices.FieldOffset(0)] public Foo theFoo; [System.Runtime.InteropServices.FieldOffset(0)] public Bar theBar; } 

but I'm not sure if this will work with objects.

0
source share

All Articles