Microsoft MVP성태의 닷넷 이야기
캐스팅...에 관해 궁금합니다. [링크 복사], [링크+제목 복사]
조회: 11600
글쓴 사람
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)
5402민성11/5/20207680안녕하세요 책을 보고 질문하나만 드릴깨요 [2]
5401민성11/3/20206753안녕하세요 이번에도 질문 하나만 드리겠습니다. [2]
5400진우10/29/20206438SQL Server 관련 몇가지 문의 [2]
5399Wpf개...10/21/20206665Binding 된 항목의 갱신 시 간헐적 끊어짐 발생 문제. [2]
5397나그네10/15/20206134.net Core 3.1 에서 Entity Framework 와 ADO.NET 선택에 관해 여쭤봅니다. [2]
5396여정욱10/15/20206218CLR heap 관련 질문 2 [2]
5395여정욱10/14/20207975CLR heap 관련 질문 [2]
5394진우10/12/202011412닷넷코어 (닷넷5) winform wpf는 리눅스/맥에서도 가능한가요? [2]
5393김세용9/23/20207925C#에서 대량의 클래스를 빠르게 생성하는 방법이 없을까요? [6]
5392전경호9/22/20207577WPF에서 WindowsFormsHost의 메모리 누수 문제 때문에 문의드립니다. [1]파일 다운로드1
5391민성9/22/20206885안녕하세요 항상 감사드립니다. 하나 질문 드리겠습니다. [1]
5390alow...9/18/20209752System.AccessViolationException 보호된메모리 부분 예외처리 [1]
5389C# 8...9/18/20207981후위 증감 연산자 오버로딩 방법 좀 알려주세요 [4]
5388영귤9/17/20208941Nullable reference type 에 Non-nullable reference type 을 대입해도 경고가 발생하지 않습니다. [2]
5387하태9/17/20207382안녕하세요! 비동기 통신과 관련하여 질문하나만 드리겠습니다! [3]
5386박민웅9/16/20209156정성태 스승님 안녕하세요 !! [1]
5385영귤9/12/202066553항 연산자에 ref 지원? [1]
5384guest9/10/20206529시작하세요! C# 8.0 프로그래밍 책에 오타가 있는 것 같습니다. [3]
5383민성9/8/20208023안녕하세요 자주 도움을 주셔서 감사드립니다. WPF에서 크롬 브라우저 삽입에 대하여 [1]
5382정씨9/4/20207170[C#] 시리얼통신 수신된 데이터를 그리드뷰에 뿌르는데 일정 시간이 지나면 버벅 거리는 이유가 뭘까요?? [3]
5381질문 있...9/4/20206942웹으로 사용하는 c#과 응용프로그램으로 사용하는 c#이 많이 다른가요?? [2]
5380yeon9/3/20207006winform 의 datagridview는 바인딩이 안 되나요? [1]
5379guest9/2/20209673시작하세요! C# 8.0 프로그래밍 책에 오타가 있습니다. [3]
5378net9/2/20207166mes 응용프로그램을 .net 웹폼으로 만들기도 하나요? [2]
5377net9/2/20206559.net 사용한 웹폼으로 응용프로그램을 만들경우 [1]
5376영귤9/1/20206951nullable 타입간의 비교연산은 그냥 가능한 건가요? [1]
... 16  17  18  19  20  [21]  22  23  24  25  26  27  28  29  30  ...