我试图弄清楚在类型本身未知时,支持拆箱的语法(简短/int/long)与其内在类型。

这是一个完全人为的例子,证明了这个概念:

 // Just a simple container that returns values as objects
 struct DataStruct
 {
  public short ShortVale;
  public int IntValue;
  public long LongValue;
  public object GetBoxedShortValue() { return ShortVale; }
  public object GetBoxedIntValue() { return IntValue; }
  public object GetBoxedLongValue() { return LongValue; }
 }

 static void Main( string[] args )
 {

  DataStruct data;

  // Initialize data - any value will do
  data.LongValue = data.IntValue = data.ShortVale = 42;

  DataStruct newData;

  // This works if you know the type you are expecting!
  newData.ShortVale = (short)data.GetBoxedShortValue();
  newData.IntValue = (int)data.GetBoxedIntValue();
  newData.LongValue = (long)data.GetBoxedLongValue();

  // But what about when you don't know?
  newData.ShortVale = data.GetBoxedShortValue(); // error
  newData.IntValue = data.GetBoxedIntValue(); // error
  newData.LongValue = data.GetBoxedLongValue(); // error
 }

在每种情况下,积分类型都是一致的,因此应该有某种形式的语法说“该对象包含一种简单的x,返回为x(即使我不知道x是什么)”。因为对象最终来自同一源,所以实际上不会有不匹配(简短!= long)。

对于一个人为的例子,我深表歉意,这似乎是演示语法的最佳方法。

谢谢。

有帮助吗?

解决方案

好吧, object 本身就是框架所知道的最通用类型。是盒装值类型(包括原始)还是其他东西都无关紧要;如果您想更具体地 除非您留在“松散地打字”的世界中 object (或在C#4中, dynamic).

但是,请注意,您可以使用条件列表来实现所需的目标:

object boxedValue = GetBoxedValue();
if (typeof(short) == boxedValue.GetType()) {
  newData.ShortValue = (short)boxedValue;
} else if (typeof(int) == boxedValue.GetType()) {
  newData.IntValue = (int)boxedValue;
} else if (typeof(long) == boxedValue.GetType()) {
  newData.LongValue = (long)boxedValue;
} else {
  // not one of those
}

编辑: 通用的“盒子”也可能会做您想要的:

public class Box<T>: IConvertible where T: struct, IConvertible {
    public static implicit operator T(Box<T> boxed) {
        return boxed.Value;
    }

    public static explicit operator Box<T>(T value) {
        return new Box<T>(value);
    }

    private readonly T value;

    public Box(T value) {
        this.value = value;
    }

    public T Value {
        get {
            return value;
        }
    }

    public override bool Equals(object obj) {
        Box<T> boxed = obj as Box<T>;
        if (boxed != null) {
            return value.Equals(boxed.Value);
        }
        return value.Equals(obj);
    }

    public override int GetHashCode() {
        return value.GetHashCode();
    }

    public override string ToString() {
        return value.ToString();
    }

    bool IConvertible.ToBoolean(IFormatProvider provider) {
        return value.ToBoolean(provider);
    }

    char IConvertible.ToChar(IFormatProvider provider) {
        return value.ToChar(provider);
    }

    sbyte IConvertible.ToSByte(IFormatProvider provider) {
        return value.ToSByte(provider);
    }

    byte IConvertible.ToByte(IFormatProvider provider) {
        return value.ToByte(provider);
    }

    short IConvertible.ToInt16(IFormatProvider provider) {
        return value.ToInt16(provider);
    }

    ushort IConvertible.ToUInt16(IFormatProvider provider) {
        return value.ToUInt16(provider);
    }

    int IConvertible.ToInt32(IFormatProvider provider) {
        return value.ToInt32(provider);
    }

    uint IConvertible.ToUInt32(IFormatProvider provider) {
        return value.ToUInt32(provider);
    }

    long IConvertible.ToInt64(IFormatProvider provider) {
        return value.ToInt64(provider);
    }

    ulong IConvertible.ToUInt64(IFormatProvider provider) {
        return value.ToUInt64(provider);
    }

    float IConvertible.ToSingle(IFormatProvider provider) {
        return value.ToSingle(provider);
    }

    double IConvertible.ToDouble(IFormatProvider provider) {
        return value.ToDouble(provider);
    }

    decimal IConvertible.ToDecimal(IFormatProvider provider) {
        return value.ToDecimal(provider);
    }

    DateTime IConvertible.ToDateTime(IFormatProvider provider) {
        return value.ToDateTime(provider);
    }

    string IConvertible.ToString(IFormatProvider provider) {
        return value.ToString(provider);
    }

    object IConvertible.ToType(Type conversionType, IFormatProvider provider) {
        return value.ToType(conversionType, provider);
    }
}

然后可以使用它代替 object;它仍然是对象引用,但也强烈键入原始结构或原始类型。

其他提示

我不完全确定您想实现的目标,但是您的数据级类型是错误的。

我想,并非所有方法都返回longValue。

struct DataStruct
{
    public short ShortVale;
    public int IntValue;
    public long LongValue;
    public object GetBoxedShortValue() { return ShortVale; }
    public object GetBoxedIntValue() { return IntValue; }
    public object GetBoxedLongValue() { return LongValue; }
}

否则,您始终可以使用转换类尝试在不同类型之间进行转换。
例如:

Convert.ToInt32(SomeObject);

如果您的意思是不同的话,请澄清您的帖子(只需点击编辑按钮并进行编辑)即可。

顺便说一句,从 object 由于所有内容的基本类型,因此可能非常容易出错。所以,一个 object 可以是任何东西,这意味着您不能总是安全转换 object 到INT或任何其他类型。

更多示例:

int value;
try
{
    value = Convert.ToInt32(someObject);
}
catch (FormatException)
{
    // the convertion is unsuccessful
}

这也很有用:

int myValue;
if (!int.TryParse(something, out myValue))
{
    //unsuccessful
}

我希望这有帮助。

你可以返回 dynamic, ,然后可以将其施放为积分类型。

正如其他人所说的那样,您的示例无法正常工作,因为您从每种方法中返回longValue,因此您将在这里得到无效的铸造异常(盒装长期不能简短)。

newData.ShortVale = (short)data.GetBoxedShortValue();

但是,使用C#4 dynamic, ,这将起作用(注意您的GetBox方法的修复程序,并 dynamic 而不是 object:

// Just a simple container that returns values as objects
struct DataStruct
{
    public short ShortVale;
    public int IntValue;
    public long LongValue;
    public dynamic GetBoxedShortValue() { return ShortValue; }
    public dynamic GetBoxedIntValue() { return IntValue; }
    public dynamic GetBoxedLongValue() { return LongValue; }
}

static void Main( string[] args )
{
    DataStruct data;

    // Initialize data - any value will do
    data.LongValue = data.IntValue = data.ShortVale = 42;

    DataStruct newData;

    newData.ShortVale = (short)data.GetBoxedShortValue();
    newData.IntValue = (int)data.GetBoxedIntValue();
    newData.LongValue = (long)data.GetBoxedLongValue();

    newData.ShortVale = data.GetBoxedShortValue(); // ok
    newData.IntValue = data.GetBoxedIntValue(); // ok
    newData.LongValue = data.GetBoxedLongValue(); // ok
}

请注意,在过去三种情况下,您不需要任何演员。但是,请注意,如果类型不对齐,则 GetBoxedShortValue() { return LongValue; }, ,最后三行将导致无效的铸造异常。 (有趣的是,前三个不会,他们只会工作,但是当您更改时 dynamic 回到 object, 他们 会抛出无效的铸造例外。)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top