简体   繁体   English

C#:运行时数据类型转换

[英]C#: run-time datatype conversion

This is my first time using StackOverflow myself. 这是我第一次自己使用StackOverflow。 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. 该项目包括一个NBT解析器,我决定自己写,因为它将用于或多或少的自定义NBT文件变体,虽然核心原则是相同的:二进制数据流与特定种类的预定义“关键字”标签。 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: 我能想到的最好的方法是制作Object类型或动态的有效负载,但这样可以隐式地完成所有转换:

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. 我想通过某种方式告诉C#从现在开始解决它,即使Payload是动态的,如果指定的值不能隐式转换为当前值的类型,它将抛出异常 - 当然,除非它完成明确。

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

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

如果您知道需要Int64,为什么不使用Convert.ToInt64?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM