2010-05-19 73 views
6

我试图找出当它的类型本身是未知的时候支持拆箱整型(short/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是什么)“。因为对象最终来自同一个来源,所以实际上不会有不匹配(short!= long)。

我为这个人为的例子表示歉意,它似乎是展示语法的最好方式。

谢谢。

+0

所有的你'GetBoxed'方法返回'LongValue'。错字? – unholysampler 2010-05-19 20:21:22

+0

你是什么意思“不可能有不匹配”?如果你知道这个类型,那么就不会有;如果你不这样做,那么可以。 – 2010-05-19 20:21:49

+1

你想如何使用拆箱的结果?如果拆箱后你不知道这种类型,那么你就无法做任何事情(除了猜测和使用'dynamic')。如果您在拆箱后知道该类型,请将其取消装箱。在你的榜样,你知道newData.IntValue只能与一个int被分配,让你_have_做'newData.IntValue =(int)的yourUnknownBoxedValue;'。如果这样做失败,则不能将其分配给newData.IntValue。如果它没有失败,那么你很好。 所以我说的是真的:你应该想出一个没有人为的例子,因为这没有意义。 – Joren 2010-05-19 20:39:50

回答

2

那么,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;它仍然是一个对象引用,但它也是强类型的原始结构或原始类型。

+0

作为边注,框架已经包含非常相似'盒'一类(尽管没有转换运算符和IConvertible):'StrongBox的'(System.Runtime.CompilerServices)。 – Ruben 2010-05-19 20:45:40

1

您可以返回dynamic,然后可以将其转换为整数类型。

2

我不完全确定你想用这个来实现什么,但是你的DataStruct类型是错误的。

我想,并非所有的方法都返回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类尝试在不同类型之间进行转换。
例如:

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 
} 

我希望这有助于。

+0

@Hans,Convert.ToInt32()要求你在编译时知道Int类型 - 这正是*我试图避免的。 – 2011-04-07 01:27:45

0

如前所述别人,你的榜样是行不通的,因为你从每个方法返回的longValue,所以你会在这里得到一个无效转换异常(一盒装长期不能转换到短)。

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

然而,使用C#4的dynamic,这将工作(注意修复您GetBoxed方法和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,他们将引发无效转换异常。)