我正在尝试找出支持将整数类型(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是什么)” 。因为对象最终来自同一个源,所以实际上不会出现不匹配(短!=长)。
我为这个人为的例子道歉,这似乎是演示语法的最佳方式。
感谢。
答案 0 :(得分: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
;它仍然是一个对象引用,但它也强烈地键入原始结构或基本类型。
答案 1 :(得分: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
}
我希望这会有所帮助。
答案 2 :(得分:1)
您可以返回dynamic
,然后可以将其转换为整数类型。
答案 3 :(得分: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
时,他们会抛出无效的强制转换异常。)