Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: run-time datatype conversion

Tags:

c#

types

dynamic

This is my first time using StackOverflow myself. I have found many answers to many of my question here before, and so I thought I would try asking something myself.

I'm working on a small project and I am a bit stuck right now. I know ways to solve my problem - just not the way I want it to be solved.

The project includes an NBT parser which I have decided to write myself since it will be used for a more or less custom variation of NBT files, though the core principle is the same: a stream of binary data with predefined "keywords" for specific kinds of tags. I have decided to try and make one class only for all the different types of tags since the structure of the tags are very similar - they all contain a type and a payload. And this is where I am stuck. I want the payload to have a specific type that, when an explicit conversion is done implicitly, throws an error.

The best I could come up with is to make the payload of type Object or dynamic but that will allow all conversions done implicitly:

Int64 L = 90000;
Int16 S = 90;
dynamic Payload; // Whatever is assigned to this next will be accepted
Payload = L; // This fine
Payload = S; // Still fine, a short can be implicitly converted to a long
Payload = "test"; // I want it to throw an exception here because the value assigned to Payload cannot be implicitly cast to Int64 (explicit casting is ok)

Is there any way of doing this? I would like to solve it by somehow telling C# that from now on, even though Payload is dynamic, it will throw an exception if the assigned value cannot be implicitly converted to the type of the current value - unless, of course, it is done explicitly.

I am open to other ways of accomplishing this, but I would like to avoid something like this:

public dynamic Payload
{
    set
    {
        if(value is ... && Payload is ...) { // Using value.GetType() and Payload.GetType() doesn't make any difference for me, it's still ugly
            ... // this is ok
        } else if(...) {
            ... // this is not ok, throw an exception
        }
        ... ... ...
    }
}
like image 309
maqhem Avatar asked Aug 01 '11 00:08

maqhem


1 Answers

Have you considered using generics? This would automatically give you compile-time checking on which conversions are allowed.

class GenericTag<T>
{
    public GenericTag(T payload)
    {
        this.Payload = payload;
    }

    public T Payload { set; get; }
}

// OK: no conversion required.
var tag2 = new GenericTag<Int64>(Int64.MaxValue);

// OK: implicit conversion takes place.
var tag1 = new GenericTag<Int64>(Int32.MaxValue);

// Compile error: cannot convert from long to int.
var tag4 = new GenericTag<Int32>(Int64.MaxValue);

// Compile error: cannot convert from string to long.
var tag3 = new GenericTag<Int64>("foo");
like image 196
Ergwun Avatar answered Oct 23 '22 12:10

Ergwun