implicit | explicit | ||
Type | Keyword | Type | Keyword |
C#에서는 사용자 정의 형변환을 지원한다.
예를 들어 아래와 같은 클래스가 있다고 생각해보자.
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public Student (string name) { Name = name; }
}
이 때 Student 클래스의 인스턴스 자체를 string 형식으로 암시적 혹은 명시적으로 변환하고 싶다면 사용자 정의 형변환을 통해 암시적/묵시적 형변환을 재정의할 수 있다.
public static implicit operator string (Student s)
{
return s.Name;
}
위 코드는 implicit을 사용하여 Student 클래스의 string에 대한 암시적 형변환을 재정의한 코드이다.
따라서 아래와 같이 사용 가능하다.
var student1 = new Student("John");
string studentName = student1; // student1.Name이 반환됨
람다식을 사용하면 재정의 구문을 다음과 같이 간략하게 작성할 수 있다.
public static implicit operator string (Student s) => s.Name;
반대로 explicit을 사용하여 명시적 형변환을 재정의할 수도 있다.
public static explicit operator int (Student s) => s.Age;
명시적 형변환을 재정의한 코드이다.
var student1 = new Student("John");
student1.Age = 17;
int studentAge = (int)student1;
명시적 형변환은 위와 같이 사용한다.
주의할 점은 같은 형식에 대해 암시적/명시적 형변환을 모두 재정의할 수 없다는 것이다.
이를테면 아래와 같이 작성하는 것은 허용되지 않는다.
public static implicit operator string (Student s) => s.Name;
public static explicit operator string (Student s) => s.Name;
위 코드는 같은 형식(string)에 대해 암시적/명시적 형변환을 모두 재정의하고 있기 때문에 컴파일 에러가 발생한다.
추가적으로, 반드시 클래스 형식이 인자로 올 필요는 없다. 아래와 같은 방식도 허용된다.
public static explicit operator Student (string str) => new Student(str);
var name = "John";
var student1 = (Student)name; // 사용자 정의 형변환을 통해 name을 생성자에 넘겨 새로운 객체가 생성되어 반환된다.
또 한가지 주의할 점이 있는데 이런식으로 사용자 정의 형변환을 통해 생성된 '인스턴스'는 완전히 새로운 객체라는 점이다.
이해하기 쉽게 또 다른 예를 들어 설명해보겠다.
public class A
{
int width;
int height;
public A (int width, int height)
{
this.width = width;
this.height = height;
}
public static explicit operator B (A a) => new B(a.width * a.height);
}
public class B
{
int area;
public B (int area) { this.area = area; }
}
위와 같은 두 클래스 A, B가 있을 때, 명시적 형변환을 통해 A의 인스턴스를 B의 참조로 변환 및 대입하려고 한다면,
var a = new A(10,20);
var b = (B)a;
위 코드에서 원하는 것은 B형식으로 변환된 a였으나, 실제로는 새로운 B의 인스턴스이다.
무슨 뜻이냐면 정상적인 원래의 캐스팅 방식이라면 a와 b는 서로 같은 인스턴스를 참조해야 하는데, 이 둘은 서로 아예 다른 인스턴스를 참조하고 있다는 뜻이다.
Bitmap bitmap = Image.FromFile("myImage.bmp");
Image image = (Image)bitmap1;
image.Dispose();
위 식에서 image를 Dispose했지만, bitmap 역시 Dispose된다. 왜냐하면 bitmap와 image는 같은 인스턴스를 참조하고 있기 때문이다.
하지만 사용자 정의 형변환으로 재정의된 캐스팅에서 예시로 든 방식을 사용할 경우, 두 참조가 서로 다른 인스턴스를 참조하게 되기 때문에 예상치 못한 결과를 가져오거나, 메모리가 누수될 수 있다는 점을 주의하자.
'C#' 카테고리의 다른 글
Test (0) | 2022.05.10 |
---|---|
Parallel.For() (0) | 2020.08.03 |
ArrayList (0) | 2020.08.03 |