Microsoft MVP성태의 닷넷 이야기
캐스팅...에 관해 궁금합니다. [링크 복사], [링크+제목 복사],
조회: 11627
글쓴 사람
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]

1  2  3  4  5  6  7  8  [9]  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
5730김재환10/7/20224539WPF에서 디스플레이 배율이 100%가 아닌 경우, Window의 포지션 정보가 부정확해지는 문제 [2]
5729김기헌10/2/20224189안녕하세요 선생님 뮤텍스 관련 질문 드립니다 [2]
5728김경환9/29/20224209그리드뷰관련마지막질문하나드리겠습니다선생님 [5]파일 다운로드1
5727김경환9/26/20224083c# 윈폼 tcp/ip 기반 데이터그리드뷰질문하나드리겟습니다 [3]
5726양승조 donator9/22/20224800C# dll 과 C++ 간 배열 전달. SafeArray [10]파일 다운로드1
5725김기헌9/21/20223694안녕하세요 선생님 윈폼 컨트롤 Dispose 관련 질문드립니다 [2]
5724감사합니...9/19/20223730스레드와 스레드 안전한 객체 사용관련 문의드립니다. [5]
5723드리렁9/13/20223656Pinned Object에 대해서 질문이 있습니다. [2]
5722김인태9/8/20223830대화상자에서 alt + tab 후킹 작업 [1]
5721우종9/7/20223983C++ DLL 과 C# 연동 문의 [2]
5720한예지 donator9/6/20223696학습 방법 질문 있습니다. [7]
5719김경한9/6/20224028안녕하세요 질문하나만드리겠습니다...! [10]
5718김민아9/2/20224061안녕하세요 생성자 호출 시 초기화 순서 질문드립니다 [2]
5716iili...8/26/20224290WinDbg 커널 디버깅에서의 thread freeze [2]
5715에릭8/19/20224693WMI 쿼리 결과값이 Windows Service와 Console 출력에서 상이한 이유가 있을까요? [9]파일 다운로드1
5714허니빠8/18/20224723.net6 hint path 를 프로젝트 단위로 지정할 수 있는 방법을 알고싶습니다 [8]
5713김기헌8/17/20224644안녕하세요 rgb 계산 오차가 있는데 원인을 모르겠습니다.. [3]
5712하태8/17/20224125안녕하세요 background service에서 user32dll 접근 질문 드리겠습니다.! [2]
5711하태8/16/20223648안녕하세요! 윈도우즈 해상도 관련 질문 드립니다. [1]
5710장성욱8/12/20223863c# 시리얼 통신 관련 질문 [3]
5709초보8/12/20223658WPF 커맨드 관련 질문 [2]
5708민성8/11/20223917안녕하세요 c#에서 화면의 배율 및 레이아웃을 변경할려면 어떻게 해야 할까요? [2]파일 다운로드1
5707민성8/10/20223551WPF 엣지 컨트롤에서 화면이 안보이는 현상 [2]파일 다운로드1
5706종규8/7/20225980WPF 에서 SVG 아이콘 사용 방법 문의 [2]
5705김기헌8/6/20224695안녕하세요 선생님 싱글톤 패턴 간단 질문 [2]
5704따봉이8/4/20224599EventHandler 관련 [1]
1  2  3  4  5  6  7  8  [9]  10  11  12  13  14  15  ...