Microsoft MVP성태의 닷넷 이야기
캐스팅...에 관해 궁금합니다. [링크 복사], [링크+제목 복사]
조회: 11570
글쓴 사람
edain
홈페이지
첨부 파일
 

안녕하세요.

C#에서는

int n = 3;
object o = n;
int m = (int)o;

위와 같이 object로 변환된 값을 실제 타입으로 캐스팅 하려면 코딩할 때 타입을 알고 있어야 캐스팅이 가능해 보입니다.
만약에 위의 코드에서 int m = o; 라고 쓰면 오류가 나죠.

하지만 VB.NET 에서는 위의 코드를 아래와 같이 변환하면

Dim n As Integer = 3
Dim o As Object = n    
Dim m As Integer = o

잘 작동합니다.

리플렉션을 해 보면 VB.NET에서는 따로 Microsoft.VisualBasic.CompilerServices.Conversions.ToInteger 라는 메서드를 사용해서 변환을 해 주는 것 같습니다.

C#에서는 위와같은 코드를 작성하려면 어떻게 해야 할까요?









[최초 등록일: ]
[최종 수정일: 9/8/2015]


비밀번호

댓글 작성자
 



2015-09-08 01시53분
VB.NET과 C#은 언어의 철학이 다릅니다. 그래서 그런 차이가 발생하는 것입니다. 제가 이전의 VB 6을 잘 몰라서 정확한 답은 아닐 수 있는데, 아마도 VB 시절부터 그 구문이 동작했기 때문에 VB.NET에서 뺄 수 없어서 가능하도록 구현했을 것입니다. (Microsoft.VisualBasic 네임스페이스에 포함된 것들은 대부분 기존 VB와의 호환을 위해 만들어 둔 것입니다.)

VB.NET은 대입될 대상 변수가 Integer이기 때문에 무조건 (성공하든 못하든) ToInteger를 불러주도록 코드를 생성해주는 것입니다. 반면, C#은 object에 어떤 타입의 인스턴스가 들어 있을지 알 수 없기 때문에 암시적 형변환이나 ToInteger 같은 메서드로 대체하지 않고 개발자의 책임하에 명시적으로 형변환을 하도록 강제하는 것입니다. (이는 C++과도 유사한 정책입니다.)
정성태
2015-09-08 02시47분
[edain] 네.. 답변 감사드립니다.^^

이러한 의문이 발생한 원인은 오래전 DataTable 로 Query 의 결과를 조회해 오고는 행마다 대응되는 클래스의 인스턴스로 생성하는 일을 하면서였습니다.
쿼리에 대응되는 클래스가 많아지자 귀찮아서 Reflection으로 DataTable의 Column Name과 똑같이 대응되는 Property Name으로 값을 넘겨 자동화를 하였었습니다.
그런데 문제는 PropertyInfo 로 대상 클래스의 Property에 값을 SetValue 메서드를 사용하려니 매개변수 타입이 object 이더라구요.
PropertyInfo를 설계하신 분 입장에선 당연히 어떤 타입의 값이 사용될지 모르는 상황에서 당연한 문제였을 것 같지만 이런식으로 쓰면 Boxing 이 많이 발생되지 않을까 하는 의문도 들었고 이런 방식 말고는 방법이 없을까? 하는 의문도 들었었습니다. 그러다가 오늘 비슷한 문제를 누군가가 이야기 하시길래 제 의문과 함께 질문을 드렸습니다.^^



[guest]
2015-09-08 04시43분
해당 문제의 박싱/언박싱이라면, VB.NET에서도 (코드에서 그것이 숨겨질 뿐) 동일하게 나타납니다.

그러게요. ^^ 자동화와 성능을 같이 잡는 것이 쉽지는 않은 것 같습니다. DataTable과 대응 클래스 같은 경우에는, 저는 예전에 "자동 소스 코드 생성기"로 처리를 했었습니다. XML로 클래스의 규격을 표현하고 그것을 XSLT를 이용해 DataTable과 대응 클래스를 자동으로 생성하게 하는 것인데, 그럴 때 XmlCodeGenerator를 써먹었습니다.

XmlCodeGenerator
; https://visualstudiogallery.msdn.microsoft.com/20163975-c675-4f1c-986f-d2489136469d
정성태
2015-09-10 06시30분
[edain] XmlCodeGenerator에 관한 글을 오래전에 성태님 글에서 본 건지...왠지 낯이 익네요^^ 감사합니다.

박싱은/언박싱은 어쩔 수 없다고 생각하고 타입을 변경하는 코드를 만들어봤습니다.
사실 위의 질문에서의 지역변수형태의 변수들은 속성으로 실제 만들어져 있는데요.
리플렉션으로 속성..즉 Property의 PropertyInfo 를 얻어와선 SetValue 메서드와 Convert.ChangeType 메서드를 사용하면 인스턴스 값의 실제 타입이 일치하든 아니든 변경은 이루어지네요.
다들 알고 계실 듯 하지만 혹여나 저처럼 고민하시는 분들이 계시면 도움이 될까 싶어 남겨 봅니다.

처음에 Convert.ChangeType 메서드를 봤을 때 어차피 타입을 변경해줘봤자 object로 반환하는데 이게 무슨 쓸모가 있지? 라는 생각이 들었었습니다.
그런데 아는 형의 리플렉션 예제 코드를 도와주며 대화를 하다보니 PropertyInfo의 SetValue는 object 타입의 값을 받아 내부적으로 실제 타입으로 변환해준다는 사실이 생각났습니다.
왜 이 생각이 이제야 났는지 참 바보같다고 생각한 오후입니다. ㅜㅜ

아래의 코드는 LINQPAD의 코드입니다.

void Main()
{
    TypeA a = new TypeA();
    a.Value = 3;
    
    TypeB b = new TypeB();
    
    // b.Value = Convert.ChangeType(a.Value, typeof(string)); // 오류. 당연한 이야기이지만 원본 데이터와 대상 속성의 타입이 다름으로 실행 불가.
    // b.Value = (string)Convert.ChangeType(a.Value, typeof(string)); // 잘 작동함. 하지만 코딩할 때 타입을 일일이 쓰는 경우가 아니고 동적 변환에는 무슨타입이 올지 알 수 없으므로 쓸모없음.
    
    // solution
    PropertyInfo piValue = b.GetType().GetProperty("Value");
    
    // piValue.SetValue(b, a.Value); // 이 코드는 원래 타입이 Int32 이기 때문에 string 값으로 대입불가
    piValue.SetValue(b, Convert.ChangeType(a.Value, piValue.PropertyType));
    
    b.Value.Dump();    
}

// Define other methods and classes here


public class TypeA
{
    public int Value { get; set; }
}

public class TypeB
{
    public string Value { get; set; }
}
[guest]
2015-09-10 06시36분
[edain] 헉...댓글이 중복이 되어버린...ㅜㅜ 하나 지워주실 수 있을까요?
아뭏든 Convert.ChangeType 이 이런 경우에는 매우 유용하게 사용될 수 있음을 이제야 깨닳은 1人 입니다.ㅜㅜ
[guest]

... 16  17  18  19  20  21  22  23  [24]  25  26  27  28  29  30  ...
NoWriterDateCnt.TitleFile(s)
5316윤현수4/7/20206253pipe 비동기방식 질문 [1]파일 다운로드1
53154/6/20206918dll파일 로드 원리? 부분에서 도움받고싶습니다. [3]
5314강성욱3/31/20208818메서드 내에서 await 2번 등장할 때의 이해 [11]파일 다운로드1
5313강성욱3/27/20206631await 2번 [1]
53121a2a...3/20/20206403Re raw data write 질문 관련 [1]파일 다운로드1
53111a2a...3/20/20207207Raw data write 관련 질문 [1]파일 다운로드1
5310아스파넬3/15/202072391초에 5회 함수호출 제한 관련 질문입니다. [1]
5309하태3/11/20209110안녕하십니까. c# Winform UI 질문드리겠습니다! [3]파일 다운로드1
5308질문3/9/20207918Window XP SP3 32bit 환경(Window Update 모두 완료)에서 .Net Framework 4.0.3 으로 빌드된 .dll 파일 gacutil.exe 등록 관련 문의 [5]
5306개발자3/9/20206774C#을 통해 인터넷 접속 가능한 이더넷을 선택할 수 있는지요? [1]
5305JaeS...3/9/20206463RAW파일 생성 질문드립니다 [8]파일 다운로드1
5303궁금하당2/27/20208759C#에서 C++ DLL읽기 (아래 글쓴이) [1]
5302궁금하당2/27/202010843C#에서 C++ DLL호출 ('PInvokeStackImbalance') [4]파일 다운로드1
5301질문합니...2/27/20206326소켓 대량 데이터 디자인 문의 [1]
5300nals...2/27/20206951vs2013에서 BinaryFormatter Serialize 후 vs2015에서 Deserialize시 예외 발생 [3]파일 다운로드1
5298질문2/26/20208337.lic 파일에 대해 질문 있습니다. [9]
5297임한승2/26/20205902vs2013에서 BinaryFormatter Serialize 후 vs2015에서 Deserialize시 예외 발생 건 [1]파일 다운로드1
5295나그네2/25/20207328클라이언트 PC 정보 조회관련.. [2]
5294닷넷초보ㅠ2/25/20207305윈폼으로 socket통신프로그램 만든후 release로 디버깅한 실행파일을 다른컴퓨터에서 실행할때 반응이없어요 [1]
5293탱코2/21/20207208검색을 하고 싶은데 어떻게 검색을 해야 할 지 모르겠습니다. [1]
5292아부리2/19/20207118XingApiNet 관련 질문 [3]
5291지현명2/15/20207848JsonConvert.Serialize 하고 Deserialize 할때 간헐적으로 한글 깨짐 현상 문의 합니다. [3]
5290베도빈2/15/20207196직접 제작한 사용자 정의 콘트롤 DLL, 실행파일에 포함시켜 배포할 수 있을까요? [1]
5288김성배2/14/20207615c# 참조추가 기능에서 DirectX 참조가 보이지 않아요.. DircetX 11 은 설치 되어 있습니다. [1]
5287C# 초...2/14/20206617프로그램 실행 질문 드립니다. [4]파일 다운로드1
5286gongs2/3/202014000윈도우 배율 및 레이아웃에 대한 질문입니다. [3]
... 16  17  18  19  20  21  22  23  [24]  25  26  27  28  29  30  ...