C# 사용자 정의 형변환 - explicit, implicit



 두 기능 모두 C#4.0부터 지원해주고 있는 기능입니다.

explicit
 명시적 사용자 정의 형변화 연산자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class Celsius
{
    private float degress;
 
public Celsius(float degress)
    {
        this.degress = degress;
    }
    //Celsius -> Fahrenheit 명시적 형변환.
    public static explicit operator Fahrenheit(Celsius c)
    {
        return new Fahrenheit((9.0f / 5.0f) * c.degress + 32);
    }
    public float Degress
    {
        get { return this.degress; }
    }
}
 
class Fahrenheit
{
    private float degress;
 
    public Fahrenheit(float degress)
    {
        this.degress = degress;
    }
    //Fahrenheit -> Celsius 명시적 형변환.
    public static explicit operator Celsius(Fahrenheit fahr)
    {
        return new Celsius((5.0f / 9.0f) * (fahr.degress - 32));
    }
    public float Degress
    {
        get { return degress; }
    }
}
 
class TextExplicit
{
    static void Main()
    {
        Fahrenheit fahr = new Fahrenheit(100.0f);
        Celsius c = (Celsius)fahr; // Fahrenheit -> Celsius explicit conversion.
 
        Fahrenheit fahr2 = (Fahrenheit)c; //Celsius -> Fahrenheit explicit conversion.
    }
}



- implicit
 암시적 사용자 정의 형변화 연산자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Digit
{
    byte value;
 
    public Digit(byte value)
    {
        if (value > 9)
        {
            throw new System.ArgumentException();
        }
        this.value = value;
    }
    // byte -> Digit 암시적 형변환.
    public static implicit operator Digit(byte b)
    { 
        return new Digit(b);
    }
    // Digit -> byte 암시적 형변환.
    public static implicit operator byte(Digit d)
    {
        return d.value;
    }
}
 
class TextImplicit
{
    static void Main()
    {
        Digit d = new Digit(3);
        byte b = d; // Digit -> byte implicit conversion.
 
        Digit dig2 = b; // byte -> Digit implicit conversion.
    }
}






참 고 : https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/statements-expressions-operators/using-conversion-operators

const보다는 readonly가 좋다.



[ Content ]

- const
    . 컴파일 타임 상수.
    . 컴파일 타임에 변수가 값으로 대체되어, 메서드 내부에서도 선언이 가능.
    . 컴파일 타임에 상수를 리터럴로 대체해야 하기 때문에, 내장된 숫자형, enum, 문자열, null과 같은 내장 자료형만 사용 가능.

- readonly
    . 런 타임 상수.
    . 컴파일 타임에 값으로 대체되는 것이 아닌, 상수에 대한 '참조'로 컴파일되어 메서드 내에서는 선언 불가능.
    . 꼭 생성과 동시에 초기화하지 않아도 되며, 생성자에서 최초 1번 초기화 가능. 그 이후에는 수정 불가능.
    . 어떤 타입과도 사용될 수 있다.


 위 내용의 런타임 상수와 컴파일 상수의 차이 중, 중요한 차이는 값이 런타임에 평가된다는 점입니다. 
런타임 상수를 참조하는 코드를 컴파일하면 컴파일 타임 상수처럼 코드를 값으로 대체하지 않고, 참조 코드를 생성합니다.
이러한 차이가 유지 및 보수에 상당한 영향을 미칩니다.


1
2
3
4
5
public class UsefulValues
{
    public static readonly int StartValue = 5;
    public const int EndValue = 10;
}



 위와 같이 정의하여 값을 사용하다 아래와 같이 수정할 때,


1
2
3
4
5
public class UsefulValues
{
    public static readonly int StartValue = 105;
    public const int EndValue = 110;
}



 수정 후, 리빌드하지 않고 사용한다면, StartValue에 대한 값은 참조 코드로 인해 런타임에 105로 읽어드리지만, EndValue는 이전 컴파일 시점에 대체되었던 10으로 값이 유지됩니다.

 이처럼 컴파일 타임 상수의 값을 수정할 때는 신중해야 하며, 모든 코드를 재컴파일해야 합니다. 하지만, 런타임 상수는 값 변경만으로도 수정이 가능하며 이진 호환성도 그대로 유지됩니다.


 이와 반대로 재컴파일 전까지 기존 값을 유지하고 싶은 경우도 있을겁니다. 이러한 경우 컴파일 타임 상수를 활용하면 됩니다.
또한, 선택적 매개 변수에 대한 기본값, 특성의 매개 변수, switch/case문의 레이블, enum 정의에 사용되는 상수 등도 컴파일 시에 사용되어야 하므로 const를 통해 초기화 해야합니다.
        - 선택적 매개 변수 : https://loveme-do.tistory.com/2

 const가 가지는 장점은 성능이 빠르다는 것인데, 이를 통해 얻을 수 있는 성능 개선 효과가 크지 않아, 위와 같은 예외적인 상황을 제외한다면 readonly를 사용하는 것이 좋습니다.




[ Digression ]


 아직 많지 않은 경험으로 사용하면서 가장 크게 느낀 장점은 readonly가 모든 타입과 사용할 수 있다는 점입니다.
상수 사용에 내장 타입과도 많이 사용하지만 직접 정의한 타입을 사용하는 경우도 많아 자주 사용할 수 밖에 없습니다. 
 위의 내용처럼 유지 및 보수 시에 확실히 상수 값 변경에 부담을 가지지 않아도 된다는 점은 크게 느낄 수 있는 장점이라 생각합니다.






참 고 : Effective C# 

C# 선택적 매개 변수와 명명된 매개 변수.



 두 기능 모두 C#4.0부터 지원해주고 있는 기능입니다.

-
선택적 매개변수
 C++
에서의 디폴트 매개 변수와 같은 기능으로, 매개 변수를 필수 또는 선택 사항으로 지정할 수 있습니다.
호출 시 모든 필수 매개 변수에 대한 인수를 제공해야 하지만 선택적 매개 변수에 대한 인수는 생략할 수 있습니다.
이 때, 선택적 매개 변수에 대해서는 기본값을 필수적으로 제공해주고 있어야하며, 필수 매개 변수 다음으로 정의해야 합니다.

 선택적 매개 변수 지원 이전에는 다음과 같이 필요한 매개 변수에 따른 함수 오버로딩으로 정의해야 했는데.....


void Person(string name);

void Person(string name, int age);
void Person(string name, int age, string address);


 위의 코드를 선택적 매개 변수 기능으로 아래와 같이 수정 가능해졌습니다!

 

void Person(string name, int age = 0, string address = “None”);



-
명명된 매개 변수
호출된 메서드, 각 인수에 대한 매개 변수를 매개 변수 이름으로 지정할 수 있습니다.


 

Person(name: “승엽, address: 서울특별시, age: 25);


 위와 같이 각 인수에 대한 매개 변수를 매개 변수 이름으로 지정하여 사용할 수 있습니다.
각 인수가
 무엇을 나타내는지 식별할 수 있어 코드의 가독성을 향상시킬 수 있고, 임의의 순서로 인수를 보낼 수 있습니다.

 또한, 위의 Person의 선택적 매개 변수 중 address에만 인자를 보내고 싶을 경우에 다음과 같은 처리도 가능합니다.

 

Person(“민호, address: 경기도);








참 고 : https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments

+ Recent posts