2010-05-19 3 views
6

유형 자체를 알 수없는 경우 내장 유형 (짧은/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

+0

"불일치가있을 수 없다"는 것은 무엇을 의미합니까? 유형을 알고 있다면 그럴 수 없습니다. 네가하지 않으면, 그럴 수있다. –

+1

언 박싱 결과를 어떻게 사용 하시겠습니까? 언 박싱 후에 유형을 모르는 경우에는 '동적'을 추측하고 사용하는 것 외에는 아무 것도 할 수 없습니다. 언 박싱 후 유형을 알고 있다면 해당 유형을 unbox하십시오. 귀하의 예제에서 newData.IntValue는 int로만 할당 될 수 있으므로 newData.IntValue = (int) yourUnknownBoxedValue;를 수행해야합니다. 이 경우 실패하면 newData.IntValue에 할당 할 수 없습니다. 실패하지 않으면 괜찮습니다. 그래서 내가 말하는 것은 실제로입니다 : 당신이 생각하지 못한 예를 생각해보아야합니다. 왜냐하면 이것은 말이되지 않기 때문입니다. – Joren

답변

2

음, object 그 자체가 프레임 워크가 알고있는 가장 일반적인 유형입니다. is가 boxed value 형 (원시적을 포함한다) 일지 어떨지는 관계 없습니다. 더 구체화하고 싶다면 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

부수적으로, 프레임 워크는 이미'Box '(변환 연산자 및 IConvertible은 없지만) 클래스와 매우 유사합니다 : StrongBox '(System.Runtime.CompilerServices). – Ruben

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 타입을 알고 있어야합니다. 이것은 피하려고하는 것입니다. –

0

각 메서드에서 LongValue를 반환하므로 예제가 작동하지 않으므로 여기서 잘못된 캐스트 예외가 발생합니다 (짧은 길이로 캐스트 할 수 없음).

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

주 마지막에 어떤 캐스트를 필요가 없습니다 : C#을 사용 4의 dynamic, 이것은 (일 수정주의하여 GetBoxed 방법과 dynamic 오히려 object보다하는 것입니다 그러나

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

, 그러나 세 개의 사례가 있는데, 유형이 일치하지 않으면 GetBoxedShortValue() { return LongValue; }처럼 마지막 세 줄은 잘못된 전송 예외가 발생합니다. (흥미롭게도 처음 세 가지는 작동하지 않지만 그냥 작동하지만 dynamicobject으로 변경하면 이됩니다.은 잘못된 캐스트 예외를 던질 것입니다.)