Section 37.5: 명시적 타입 변환 (Explicit Casting)

만약 하나의 값이 다른 특정 타입에 해당한다는 사실을 알고 있다면, 해당 타입이 필요한 상황에 맞추어 값을 명시적으로 (explicitly) 타입 변환하여 사용할 수 있다.

object value = -1; int number = (int) value; Console.WriteLine(Math.Abs(number));

만약 위 예제에서 valueMath.Abs() 메소드에 직접 파라미터로 전달한다면, Math.Abs()object 를 파라미터로 받는 오버로드 (overload) 가 정의되어 있지 않기에 컴파일 오류가 발생할 것이다.

만약 value 가 실제로는 int 타입으로 변환될 수 없는 값인 경우, 위 예제 코드의 두번째 라인은 InvalidCastException 예외를 발생시킬 것이다.

본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 37.4: LINQ 타입 변환 (Casting) 연산들

아래와 같은 타입을 가지고 있다고 가정해 보자:

interface IThing { } class Thing : IThing { }

LINQ 는 Enumerable.Cast<>()Enumerable.OfType<>() 확장 메소드를 통해, IEnumerable<> 의 컴파일 타임의 제네릭 타입을 다른 타입으로 변환시킨 프로젝션을 생성할 수 있도록 지원하고 있다.

IEnumerable<IThing> things = new IThing[] {new Thing()}; IEnumerable<Thing> things2 = things.Cast<Thing>(); IEnumerable<Thing> things3 = things.OfType<Thing>();

things2 에 값이 할당 (evaluate) 될 때는, Cast<>() 메소드가 things 안에 들어있는 모든 값들에 대해 Thing 타입으로의 변환을 시도할 것이다. 만약, 하나라도 변환이 불가능한 경우가 있다면 InvalidCastException 예외가 발생될 것이다.

things3 에 값이 할당 (evaluate) 될 때는, OfType<>() 메소드가 동일한 작업을 수행할 것이나, 타입 변환 불가시에는 예외를 발생시키는 대신 해당 값을 생략하고 진행하게 될 것이다.

이 메소드들의 제네릭 타입으로 인해, 변환 연산자 (conversion operator) 사용이나 숫자 변환을 사용할 수 없다.

역주: 이 부분에 대한 정확한 이해가 어려워, 비슷한 사례를 Stack Overflow 에서 찾아보았습니다. 좀 더 상세한 설명이 필요하신 분들은 아래 링크 참조하시면 될 것 같습니다. https://stackoverflow.com/questions/41168927/how-to-use-ienumerable-cast-and-toarray-to-convert-int-array-to-an-enum-arr

double[] doubles = new[]{1,2,3}.Cast<double>().ToArray(); // InvalidCastException 이 발생된다

이러한 경우 .Select() 안에서 변환을 수행하는 방법을 사용할 수 있다:

double[] doubles = new[]{1,2,3}.Select(i => (double)i).ToArray();
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 37.3: 변환 연산자 (Conversion Operator)

C# 에서는, 각 타입들은 사용자 정의 변환 연산자 (custom Conversion Operator) 를 명시할 수 있으며, 이는 명시적 혹은 묵시적 타입 변환을 통해 값을 다른 타입과 상호 변환을 시킬 수 있다. 예를 들어, JavaScript 표현식 하나를 나타내는 아래와 같은 클래스가 있다고 가정해 보자:

public class JsExpression { private readonly string expression; public JsExpression(string rawExpression) { this.expression = rawExpression; } public override string ToString() { return this.expression; } public JsExpression IsEqualTo(JsExpression other) { return new JsExpression("(" + this + " == " + other + ")"); } }

만약 두개의 JavaScript 값 비교를 나타내는 새로운 JsExpression 객체를 생성하고자 한다면, 아래와 같은 코드를 작성할 수 있을 것이다:

JsExpression intExpression = new JsExpression("-1"); JsExpression doubleExpression = new JsExpression("-1.0"); Console.WriteLine(intExpression.IsEqualTo(doubleExpression)); // (-1 == -1.0)

만약 JsExpression 클래스에 명시적 변환 연산자를 (explicit conversion operator) 추가해 준다면, 해당 명시적 변환을 통해 더욱 간단한 타입 변환을 수행할 수 있을 것이다.

public static explicit operator JsExpression(int value) { return new JsExpression(value.ToString()); } public static explicit operator JsExpression(double value) { return new JsExpression(value.ToString()); } // 사용 예제: JsExpression intExpression = (JsExpression)(-1); JsExpression doubleExpression = (JsExpression)(-1.0); Console.WriteLine(intExpression.IsEqualTo(doubleExpression)); // (-1 == -1.0)

아니면, 이 연산자들을 암묵적 (implicit) 연산자로 변경함으로써 더욱 손쉬운 문법을 제공할수도 있을 것이다.

public static implicit operator JsExpression(int value) { return new JsExpression(value.ToString()); } public static implicit operator JsExpression(double value) { return new JsExpression(value.ToString()); } // 사용 예제: JsExpression intExpression = -1; Console.WriteLine(intExpression.IsEqualTo(-1.0)); // (-1 == -1.0)
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 37.2: 다중 상속된 객체를 원하는 기본 (base) 타입으로 캐스팅하기

다음과 같이 정의가 되어 있다고 가정할 때 :

public interface IMyInterface1 { string GetName(); } public interface IMyInterface2 { string GetName(); } public class MyClass : IMyInterface1, IMyInterface2 { string IMyInterface1.GetName() { return "IMyInterface1"; } string IMyInterface2.GetName() { return "IMyInterface2"; } }

객체를 기본 타입으로 캐스팅하는 예제 :

MyClass obj = new MyClass(); IMyInterface1 myClass1 = (IMyInterface1)obj; IMyInterface2 myClass2 = (IMyInterface2)obj; Console.WriteLine("I am : {0}", myClass1.GetName()); Console.WriteLine("I am : {0}", myClass2.GetName()); // 출력 결과 : // I am : IMyInterface1 // I am : IMyInterface2
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 37.1: 타입 변환 (casting) 없이 타입 호환성 여부 확인하기

만약, 특정 변수가 주어진 타입을 상속 (extend) 혹은 구현 (implement) 하는지를 확인하고자 하나 해당 타입으로의 타입 변환 (casting) 을 수행하지는 않고 싶을 경우, is 연산자를 사용할 수 있다.

if(value is int) { Console.WriteLine(value + "is an int"); }
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 36.2: MSDN 의 묵시적 (implicit) 연산자 예제

class Digit { public Digit(double d) { val = d; } public double val; // Digit 을 double 타입으로 변환하는 사용자 정의 연산자 public static implicit operator double(Digit d) { Console.WriteLine("Digit to double implict conversion called"); return d.val; } // double 타입을 Digit 으로 변환하는 사용자 정의 연산자 public static implicit operator Digit(double d) { Console.WriteLine("double to Digit implict conversion called"); return new Digit(d); } } class Program { static void Main(string[] args) { Digit dig = new Digit(7); // 아래 코드는 묵시적 "double" 연산자를 호출한다 double num = dig; // 아래 코드는 묵시적 "Digit" 연산자를 호출한다 Digit dig2 = 12; Console.WriteLine("num = {0} dig2 = {1}", num, dig2.val); Console.ReadLine(); } }

출력 결과:

Digit to double implict conversion called double to Digit implict conversion called num = 7 dig2 = 12

.NET Fiddle 에서 라이브 데모 확인하기

본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 36.1: 명시적 (explicit) 타입 변환하기

using System; namespace TypeConversionApplication { class ExplicitConversion { static void Main(string[] args) { double d = 5673.74; int i; // double 타입을 int 타입으로 변환한다. i = (int) d; Console.WriteLine(i); Console.ReadKey(); } } }
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 35.4: 컴파일 시점에는 알 수 없는 특정 타입 처리하기

아래의 두 클래스는 동일한 결과를 보여준다:

class IfElseExample { public string DebugToString(object a) { if (a is StringBuilder) { return DebugToStringInternal(a as StringBuilder); } else if (a is List < string > ) { return DebugToStringInternal(a as List < string > ); } else { return a.ToString(); } } private string DebugToStringInternal(object a) { // Fall Back return a.ToString(); } private string DebugToStringInternal(StringBuilder sb) { return $"StringBuilder - Capacity: {sb.Capacity}, MaxCapacity: {sb.MaxCapacity}, Value: {sb.ToString()}"; } private string DebugToStringInternal(List < string > list) { return $"List<string> - Count: {list.Count}, Value: {Environment.NewLine + "\t " + string.Join(Environment.NewLine + "\t ", list.ToArray())}"; } } class DynamicExample { public string DebugToString(object a) { return DebugToStringInternal((dynamic) a); } private string DebugToStringInternal(object a) { // Fall Back return a.ToString(); } private string DebugToStringInternal(StringBuilder sb) { return $"StringBuilder - Capacity: {sb.Capacity}, MaxCapacity: {sb.MaxCapacity}, Value: {sb.ToString()}"; } private string DebugToStringInternal(List < string > list) { return $"List<string> - Count: {list.Count}, Value: {Environment.NewLine + "\t " + string.Join(Environment.NewLine + "\t ", list.ToArray())}"; } }

위 예제에서 dynamic 을 사용시의 장점은, 처리를 위한 새로운 타입을 추가하고자 할 때, DebugToStringInternal 메소드에 해당 타입에 대한 overload 만 하나 추가해주면 된다는 점이다. 이는 해당 메소드 호출 시 일일이 원하는 타입으로 타입 변환 (cast) 을 할 필요가 없다는 추가적인 장점이 있다.

본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

+ Recent posts