Microsoft MVP성태의 닷넷 이야기
캐스팅...에 관해 궁금합니다. [링크 복사], [링크+제목 복사]
조회: 11606
글쓴 사람
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)
5155세퉁5/7/201910354관리자 권한으로 실행 시 알림창(?) 없이 바로 실행 시킬 수 있는 방법이 있을까요?? [2]파일 다운로드1
5154Soul...5/4/20197233NamedPipe 질문드립니다. [2]
5153개태5/4/20198186WCF RESTful Service에서 enum을 parameter로 쓰는방법 [2]
5152세퉁5/3/20199312인터넷 시간을 불러와 pc에 적용 시키고 싶습니다. [3]파일 다운로드1
5151이대희5/3/20197421C# 7.3으로 개정판 출간 계획이 있으신가요? [1]
5150김이현5/2/20198800C# 딕셔너리 생성에 대해 질문드립니다. [1]
5149민성5/1/20197053ftp 이미지 업로드중 [1]
5148wpf질문4/30/20197412특정 사이트를 wpf에서 popup을 항상 허용하게 할려면 어떻게 해야할까요? [5]
5147민성4/30/20196425wpf에서 작업관리자를 띠울려면 어떻게 해야 하나요? [1]
5146불파겐4/25/20196489하나의 필드를 여러 스레드에서 읽어갈 때 스레드 동기화를 하지 않으면 문제가 생길까요? [2]
5145e구름4/17/20199465Properties.Setting.Default값에 대해 질문드립니다. [2]
5144성태님 ...4/17/20196651질문하시기 전에 10000 페이지 오류 납니다. [1]
5143헌이4/16/20197580윈도우 작업표시줄에 프로그램 띄우기 [2]파일 다운로드1
5142cab2...4/9/201913166C#으로 만든 DLL 배포하기 [10]
5141하늘사랑4/5/20198051Axinterop 래퍼에 관해서 질문드립니다. [7]
5140게스트4/1/20197685안녕하세요. 초보 개발자입니다. SD리더기에서 SD카드를 꽂으면 발생하는 이벤트 문의 [2]
5139김이현3/28/201910896C#에서 CRON 같은 스케줄러를 사용하려면 어떻게 해야 하나요? [3]
5138김지원3/22/20198530유니티 쉐이더에서 오로지 포워드 애드 패스로만 만들 수 있을까요? [1]
5137세퉁3/22/201910474wpf 쓰레드에 대해 질문 있습니다. [4]
5136KGY3/13/20197162안녕하세요 닷넷코어 콘솔 프로그램 관련 질문입니다. [1]
5135러쎌3/13/20197589ASP.NET 공부 관련해서 문의를 드립니다. [1]
5134이정호3/12/20196985SampleProfiler 예제를 이용한 Class 객체의 접근 문의 [1]파일 다운로드1
5133ㅇㅇ3/12/20197867멀티코어사용 방법에 궁금한것이 있습니다. [3]
5132존기미3/3/20198110Physical Disk Access문의 [1]
5131강용규2/25/20197220c# 개발자입니다. 타이머 질문드립니다. [1]
5130노인코래방2/25/201910748C#에서 가장 좋은 성능을 보이는 파일 읽고 쓰는 방법이 무엇인가요? [2]
... 16  17  18  19  20  21  22  23  24  25  26  27  28  [29]  30  ...