본문 바로가기
개발/Unity 내일배움캠프 TIL

C# 연산자 오버로딩과 인덱서(Indexer)

by 석시 2023. 8. 21.



class를 열심히 만드는 과정에서, C#에서 기본적으로 지원하는 연산자들에 기능을 부여할 수 있다!

vector 클래스를 만든다고 쳤을 때 +가 vector의 합을 계산하도록 기능하게 만들 수 있다는 것.

기본적인 연산자 오버로드

public class Vector2
{
    private int _x;
    public int X { get; set; }
    private int _y;
    public int Y { get; set; }

    public Vector2() { X = 0; Y = 0; }
    public Vector2(int x, int y)
    {
        X = x;
        Y = y;
    }

    public static Vector2 operator +(in Vector2 p1, in Vector2 p2)
    {
        return new Vector2(p1.X + p2.X, p1.Y + p2.Y);
    }
}

operator 키워드를 이용하여 연산자 오버로드가 가능하다.

단항 연산자의 경우는 매개변수를 하나, 이항 연산자의 경우는 매개변수를 두 개 받는다.

이때 가장 앞에 오는 매개변수가 this로 취급된다고 보면 된다.

오버로드 가능한 연산자들

1. 단항 연산자

+x-x!x~x++--truefalse

true랑 false도 연산자인 건 처음 알았다.

public static bool operator true(LaunchStatus x) => x == Green || x == Yellow;
public static bool operator false(LaunchStatus x) => x == Red;

2. 이항 연산자

사칙연산 (+ 모듈러 연산), 비트 연산자 등이 모두 오버로딩이 가능하다.

3. 비교 연산자

비교 연산자는 반드시 반대되는 경우와 함께 짝으로 오버로드해줘야 함에 주의하자.

예를 들면 ==를 오버로드할 때는 반대인 !=를 같이 오버로드해줘야 한다.

<>=, ><=가 서로 짝이다.

오버로드할 수 없는 연산자

오버로드가 가능할 것 같은데 안되는 연산자들은, 다른 연산자가 오버로드 되면 따라 오버로드되는 방식이거나 다른 방법을 통해 할 수 있는 연산자들이다.

1. 조건부 논리 연산자

&&및 || 연산자는 &| 연산자의 조건부 버전이다.

해당 조건부 논리 연산자를 오버로딩 할 수 없는 대신에, 그냥 &| 연산자를 사용하면 된다.

&| 연산자의 오버로딩이 &&및 || 연산자의 오버로딩으로 간주되는 경우도 있다.

해당 조건부 연산자가 어떻게 작동하는지를 알면 되는데, && 연산자는 T.false(x) ? x : T.&(x, y)와 동일하게 작동한다.

이말은 즉슨? false 연산자와 & 연산자가 오버로드 되면 && 연산자도 오버로드된다는 말이다.

|| 연산자는 마찬가지로 T.true(x) ? x : T.|(x, y)와 동일하게 작동한다.

2. 인덱스 접근

배열 접근의 오버로딩은 인덱서라는 것을 통해 가능하다!

인덱서 (Indexer)

public class CodeInstanceContainer<T>
{
		private T[] _data = new T[1000];

    public T this[int i]
    {
        get
        {
            if (i < 0) throw new InvalidOperationException();
            return _data[i];
        }
        set
        {
            while (i >= _data.Length) { increaseCapacity(Capacity << 1); }
            _data[i] = value;
        }
    }
		
}

다음과 같은 방식으로 설정한 클래스의 인덱스 접근이 가능하다.

3. 변환 연산자 (캐스트)

암시적 변환은 implicit, 명시적 변환은 explicit 키워드를 이용해서 가능하다.

implicit과 explicit

using System;

public readonly struct Digit
{
    private readonly byte digit;

    public Digit(byte digit)
    {
        if (digit > 9)
        {
            throw new ArgumentOutOfRangeException(nameof(digit), "Digit cannot be greater than nine.");
        }
        this.digit = digit;
    }

    public static implicit operator byte(Digit d) => d.digit;
    public static explicit operator Digit(byte b) => new Digit(b);

    public override string ToString() => $"{digit}";
}

public static class UserDefinedConversions
{
    public static void Main()
    {
        var d = new Digit(7);

        byte number = d;
        Console.WriteLine(number);  // output: 7

        Digit digit = (Digit)number;
        Console.WriteLine(digit);  // output: 7
    }
}

4. 이진 연산자

+=-=*=/=%=&=|=^=<<=>>=>>>=

얘네는 사실 이해하기 그리 어렵진 않다.

짝이 되는 연산을 오버로드 해주면 이진 연산도 암시적으로 오버로드 되는 방식.

5. 불가능한 연산자

얘넨 그냥 안된다.


Uploaded by N2T

'개발 > Unity 내일배움캠프 TIL' 카테고리의 다른 글

C# Sort() 메서드 다루기  (0) 2023.08.23
C# DataTable 간단 사용법  (0) 2023.08.22
코드 컨벤션  (0) 2023.08.18
C# 생성자와 소멸자 그리고 가비지 컬렉터  (0) 2023.08.17
C# 언어 기본 구조  (0) 2023.08.14