NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 학습
  • 매뉴얼

    학습


    C# 33. 연산자 오버로딩. (Operator overloading)

    페이지 정보

    본문

    안녕하세요. 소심비형입니다. 오늘은 연산자 오버로딩에 대해 알아보겠습니다. 이전에 이미 메소드와 생성자에 대해 오버로딩을 알아봤는데요. 관련 내용은 아래 링크에서 확인할 수 있습니다.

    메소드 오버로딩 ]

    생성자 오버로딩 ]

     

    C#에서는 operator 키워드로 static method를 정의하여 연산자를 오버로딩할 수 있습니다. 사실 값형식도 모두 객체이며 그 내부에 연산자가 정의되어 있다고 볼 수 있습니다. 이는 Java와 동일합니다. 일반적인 업무 환경에서 연산자 오버로딩을 사용할 일은 그리 많지 않을겁니다. 일반적으로 객체 지향 프로그래밍보다는 절차 지향 프로그래밍에 더 익숙하기 때문인데요. 유지보수 측면을 배제한다면 코드를 이해하는데 더 쉬울수도 있습니다^^;

    VTPdkyG.png

     

     

    개발 3년차 정도 되었다면 객체 지향과 절차 지향의 장단점을 한번 읽어보세요. 사실 처음 개발에 입문하는거라면 이 둘의 장점과 단점에 대해 잘 이해가 가지 않을겁니다.

    연산자 오버로딩의 문법은 아래와 같습니다.

    1. public static 반환형식 operator 연산자 (object1)

    2. public static 반환형식 operator 연산자 (object1, object2)

     

    위의 코드에서 연산자에는 +, -와 같은 연산자를 말하며, 반환형식은 반환될 값의 형식입니다. 위에서도 말했듯이 연산자 오버로딩은 정적(static) 형식으로 나타내야 합니다. object1은 정의된 클래스의 형식이어야 합니다. 아래 표는 C#에서 오버로딩할 수 있는 연산자를 표로 나타내고 있습니다.

    연산자 오버로드 가능성
    +-!~++--truefalse 이러한 단항 연산자는 오버로드할 수 있습니다.
    +-*/%&| , ^<<>> 이러한 이항 연산자는 오버로드할 수 있습니다.
    ==!=<><=>= 비교 연산자는 오버로드할 수 있지만 이 표 다음에 오는 참고 사항을 참조하세요.
    &&|| 조건부 논리 연산자는 오버로드할 수 없지만 오버로드할 수 있는 &및 | 를 사용하여 계산할 수 있습니다.
    [] 배열 인덱싱 연산자는 오버로드할 수 없지만 인덱서를 정의할 수 있습니다.
    (T)x 캐스트 연산자는 오버로드할 수 없지만 새 변환 연산자를 정의할 수 있습니다(explicit 및 implicit 참조).
    +=-=*=/=%=&=|=^=<<=>>= 할당 연산자는 오버로드할 수 없지만 예를 들어 +=는 오버로드할 수 있는 +를 사용하여 계산됩니다.
    =.?:??->=>f(x)ascheckeduncheckeddefaultdelegateisnewsizeoftypeof 이러한 연산자는 오버로드할 수 없습니다.

     

     

    비교 연산자는 오버로드될 경우 쌍으로 오버로드되어야 합니다. ==가 오버로드되면 !=도 오버로드되어야 하고, <와 >, <=와 =>의 경우도 동일합니다. 참고로 ==는 Equals 메소드도 함께 오버라이딩해야 합니다. 이 둘은 같은 의미이기 때문에 일관성을 유지하기 위해 반드시 처리해야 합니다.

    비주얼 스튜디오를 실행한 후 아래와 같이 코드를 작성하세요.

    Program.cs

    using System;
    
    namespace OperatorOverloading
    {
        class Program
        {
            static void Main(string[] args)
            {
                var x = new MyInt(10);
                var y = new MyInt(90);
                Console.WriteLine((++x).value);
                Console.WriteLine((x + y).value);
                Console.ReadKey();
            }
        }
     
        class MyInt
        {
            public int value; public MyInt() : this(0) { }
            public MyInt(int i) { this.value = i; }
            public static MyInt operator ++(MyInt x) { return new MyInt(x.value + x.value); }
            public static MyInt operator +(MyInt x, MyInt y)
            {
                return new MyInt(x.value + y.value);
            }
        }
    }

     

     

    위 프로그램을 실행하면 20, 110이라는 결과가 나올겁니다. 첫번째는 이해가 가지만 두번째 값은 왜 110인가에 대해 의문이 있을 수 있습니다. 이는 다음 챕터에서 알아볼 참조 타입에 대한 이해가 있어야 합니다. 우선은 그렇다는 것만 알고 넘어가죠. 파라메터를 하나만 넘기면 단항 연산자 오버로딩이며, 두개를 넘기면 이항 연산자 오버로딩입니다. 아래 표는 단항, 이항 연산자를 나타냅니다.

    연산자 이름 형식
    , 쉼표 이항
    ! 논리 NOT 단항
    != 같지 않음 이항
    % 모듈러스 이항
    %= 모듈러스 대입 이항
    & 비트 AND 이항
    & Address-of 단항
    && 논리적 AND 이항
    &= 비트 AND 대입 이항
    ( ) 함수 호출
    ( ) 캐스트 연산자 단항
    * 곱하기 이항
    * 포인터 역참조 단항
    *= 곱하기 할당 이항
    + 더하기 이항
    + 단항 더하기 단항
    ++ 증가 1 단항
    += 더하기 할당 이항
    빼기 이항
    단항 부정 연산자 단항
    –– 감소 1 단항
    –= 빼기 할당 이항
    –> 멤버 선택 이항
    –>* 멤버 포인터 선택 이항
    / 나눗셈 기호 이항
    /= 나누기 할당 이항
    < 보다 작음 이항
    << 왼쪽 <Shift> 이항
    <<= 왼쪽 시프트 할당 이항
    <= 작거나 같음 이항
    = 할당 이항
    == 같음 이항
    > 보다 큼 이항
    >= 크거나 같음 이항
    >> 오른쪽 Shift 이항
    >>= 오른쪽 시프트 할당 이항
    [ ] 배열 첨자
    ^ 배타적 OR 이항
    ^= 배타적 OR 할당 이항
    | 포괄적 비트 OR 이항
    |= 포괄적 비트 OR 대입 이항
    || 논리적 OR 이항
    ~ 1의 보수 단항
    delete Delete
    new New
    conversion operators conversion operators 단항

     

     

    C#의 연산자에서 이미 알아본 내용이긴 하지만 한번 더 언급하자면, 단항 연산자는 사전 증가와 사후 증가 두가지가 존재합니다. ++x, x++처럼 말이죠.

    Guo1kPQ.jpg

     

     

    첫번째 예제에 대해 간단하게 설명해보면, int 값을 하나 갖는 클래스인 MyInt에 단항 연산자 오버로딩과 이항 연산자 오버로딩이 정의되어 있습니다. 그렇기 때문에 ++과 + 연산을 통해 MyInt type을 반환받을 수 있습니다. 만약, 아래와 같은 식을 사용한다면 에러가 발생하게 됩니다. 연산자 정의가 없기 때문이죠. int 객체등 다른 클래스 객체와의 연산을 위해서는 연산자를 다중 오버로딩해야 합니다.

    MyInt m = myInt + 100;MyInt m = 100 + myInt;

     

    만약, 위 코드가 정상적으로 동작하게 하려면 아래처럼 연산자 다중 오버로딩을 구현하면 됩니다.

    Program.cs

    using System;
    
    namespace OperatorOverloading
    {
        class Program
        {
            static void Main(string[] args)
            {
                var x = new MyInt(10);
                var y = new MyInt(90);
                Console.WriteLine((++x).value);
                Console.WriteLine((x + y).value);
     
                // 다중 연산자 오버로딩            
                Console.WriteLine(new MyInt(10) + 100);
                Console.WriteLine(100 + new MyInt(10));
                Console.ReadKey();
            }
        }
        class MyInt
        {
            public int value; public MyInt() : this(0) { }
            public MyInt(int i) { this.value = i; }
     
            // 다중 연산자 오버로딩        
            public static int operator +(MyInt x, int y) { return x.value + y; }
            public static int operator +(int x, MyInt y) { return x + y.value; }
            public static MyInt operator ++(MyInt x) { return new MyInt(x.value + x.value); }
            public static MyInt operator +(MyInt x, MyInt y)
            {
                return new MyInt(x.value + y.value);
            }
        }
    }
    

     

     

    사실 자주 사용되지 않다보니 필요할 때마다 찾곤 하는데요. 주로 Statistics Engine이나 금융, 통계쪽에서 좀 사용하고 있습니다. 제가 알고 있는 건 그렇습니다-_-; 어쩌면 수많은 분야에서 사용되고 있을지도 모르죠. 아무튼, 복잡한 연산을 담당하는 객체끼리 연산하기 위한 용도로 사용됩니다. 제조쪽은 Process offset을 계산할 때 사용되곤 합니다.

     

    다음 시간에...

    • 네이버 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 카카오스토리 공유하기
    추천0 비추천0

    댓글목록

    등록된 댓글이 없습니다.