programing

개체를 T로 캐스팅

nasanasas 2020. 10. 11. 10:43
반응형

개체를 T로 캐스팅


XmlReader.NET 클래스로 XML 파일을 구문 분석하고 있으며 일반적으로 다른 특성을 읽는 일반 구문 분석 함수를 작성하는 것이 현명하다고 생각했습니다. 다음 기능을 생각해 냈습니다.

private static T ReadData<T>(XmlReader reader, string value)
{
    reader.MoveToAttribute(value);
    object readData = reader.ReadContentAsObject();
    return (T)readData;
}

내가 깨달았을 때, 이것은 내가 계획 한대로 완전히 작동하지 않습니다. 이 같은 기본 형식에 오류가 발생 int또는 double캐스트는 변환 할 수 없기 때문에, string숫자 입력합니다. 내 기능이 수정 된 형태로 우세 할 수있는 방법이 있습니까?


먼저 캐스팅 할 수 있는지 확인합니다.

if (readData is T) {
    return (T)readData;
} 
try {
   return (T)Convert.ChangeType(readData, typeof(T));
} 
catch (InvalidCastException) {
   return default(T);
}

Convert.ChangeType 을 사용해 보셨습니까 ?

메서드가 항상 이상한 문자열을 반환하지만 요점을 벗어난다면이 변경된 코드가 원하는 작업을 수행 할 수 있습니다.

private static T ReadData<T>(XmlReader reader, string value)
{
    reader.MoveToAttribute(value);
    object readData = reader.ReadContentAsObject();
    return (T)Convert.ChangeType(readData, typeof(T));
}

시험

if (readData is T)
    return (T)(object)readData;

유형이 참조 유형이되도록 요구할 수 있습니다.

 private static T ReadData<T>(XmlReader reader, string value) where T : class
 {
     reader.MoveToAttribute(value);
     object readData = reader.ReadContentAsObject();
     return (T)readData;
 }

그런 다음 값 유형과 TryParse를 사용하는 다른 작업을 수행하십시오.

 private static T ReadDataV<T>(XmlReader reader, string value) where T : struct
 {
     reader.MoveToAttribute(value);
     object readData = reader.ReadContentAsObject();
     int outInt;
     if(int.TryParse(readData, out outInt))
        return outInt
     //...
 }

실제로 여기서 문제는 ReadContentAsObject를 사용하는 것입니다. 불행히도이 방법은 기대에 부응하지 않습니다. 값에 가장 적합한 유형을 감지해야하지만 실제로는 문자열을 반환합니다 (Reflector를 사용하여 확인할 수 있음).

그러나 특정 경우에는 캐스팅하려는 유형을 이미 알고 있으므로 잘못된 방법을 사용하고 있다고 말할 것입니다.

대신 ReadContentAs를 사용해보십시오. 정확히 필요한 것입니다.

private static T ReadData<T>(XmlReader reader, string value)
{
    reader.MoveToAttribute(value);
    object readData = reader.ReadContentAs(typeof(T), null);
    return (T)readData;
}

아마도 문자열에서 T로 변환 할 델리게이트를 매개 변수로 전달할 수 있습니다.


'클래스'제약 조건을 추가합니다 (또는 실행 된 T 개체의 기본 클래스 또는 인터페이스와 같이 더 자세히).

private static T ReadData<T>(XmlReader reader, string value) where T : class
{
    reader.MoveToAttribute(value);
    object readData = reader.ReadContentAsObject();
    return (T)readData;
}

또는 where T : IMyInterface또는 where T : new()


Actually, the responses bring up an interesting question, which is what you want your function to do in the case of error.

Maybe it would make more sense to construct it in the form of a TryParse method that attempts to read into T, but returns false if it can't be done?

    private static bool ReadData<T>(XmlReader reader, string value, out T data)
    {
        bool result = false;
        try
        {
            reader.MoveToAttribute(value);
            object readData = reader.ReadContentAsObject();
            data = readData as T;
            if (data == null)
            {
                // see if we can convert to the requested type
                data = (T)Convert.ChangeType(readData, typeof(T));
            }
            result = (data != null);
        }
        catch (InvalidCastException) { }
        catch (Exception ex)
        {
            // add in any other exception handling here, invalid xml or whatnot
        }
        // make sure data is set to a default value
        data = (result) ? data : default(T);
        return result;
    }

edit: now that I think about it, do I really need to do the convert.changetype test? doesn't the as line already try to do that? I'm not sure that doing that additional changetype call actually accomplishes anything. Actually, it might just increase the processing overhead by generating exception. If anyone knows of a difference that makes it worth doing, please post!

참고URL : https://stackoverflow.com/questions/899629/cast-object-to-t

반응형