프로그래밍/C#

[C#] 동등성 (Equality)

갓똥 2020. 2. 4. 16:03
728x90
반응형

1. 참조 타입(reference type)의 동등성(Equality)

using System;

class Point {
    private int x = 0;
    private int y = 0;
    
    public Point(int xPos, int yPos) {
        x = xPos;
        y = yPos;
    }
}

class Program {
    static void Main() {
        Point p1 = new Point(1, 1);
        Point p2 = p1;
        Point p3 = new Point(1, 1);
        
        // 방법1. == 연산자 사용
        // 기본 동작 : 참조(주소)가 동일한가 ?
        Console.WirteLine(p1 == p2);  // true
        Console.WriteLine(p1 == p3);  // false
        
        // 방법2. Equals() 가상함수 사용
        // 기본 동작 : 참조가 동일한가 ?
        Console.WriteLine(p1.Equals(p2));  // true
        Console.WriteLine(p1.Equals(p3));  // false
    }
}

 ① 객체의 동등성(Equality)를 조사하는 방법

    => == 연산자 사용

    => Equals() 가상 메소드 사용

 

C#에는 참조타입과 값타입이 구별되니 두 가지를 모두 보아야 한다.
먼저 위의 코드로 참조타입을 먼저 보자.

먼저 위의 코드에서 객체 생성을 그림으로 보면 위와 같다.
이제 코드에서 방법1인 == 연산자를 사용하여 보자.
== 연산자는 기본동작이 참조(주소)가 동일한지를 확인하므로 p1과 p2는 같지만 p3는 다르다고 나온다.
Equals() 함수도 참조가 동일한지 확인하므로 위와 같은 결과값이 나온다.
하지만 코딩을 하다보면 값이 같을 경우에 대한 처리를 하고 싶을 수 있는데 이럴 경우
Equals() 가 가상함수 이므로 재정의 하여 사용하면 된다.

 

using System;

class Point {
    private int x = 0;
    private int y = 0;
    
    public Point(int xPos, int yPos) {
        x = xPos;
        y = yPos;
    }
    
    public override bool Equals(object obj) {
        Point pt = (Point)obj;
        
        return x == pt.x && y == pt.y;
    }
}

class Program {
    static void Main() {
        Point p1 = new Point(1, 1);
        Point p2 = p1;
        Point p3 = new Point(1, 1);
        
        // 방법1. == 연산자 사용
        // 기본 동작 : 참조(주소)가 동일한가 ?
        Console.WirteLine(p1 == p2);  // true
        Console.WriteLine(p1 == p3);  // false
        
        // 방법2. Equals() 가상함수 사용
        // 기본 동작 : 참조가 동일한가 ?
        Console.WriteLine(p1.Equals(p2));  // true
        Console.WriteLine(p1.Equals(p3));  // true
    }
}

 

위와 같이 함수 재정의로 처리 가능하다.
반대로 == 연산자도 연산자 재정의로 처리가 가능하다. 

 

using System;

class Point {
    private int x = 0;
    private int y = 0;
    
    public Point(int xPos, int yPos) {
        x = xPos;
        y = yPos;
    }
    
    public static bool operator==(Point p1, Point p2) {
        return p1.x == p2.x && p1.y == p2.y;
    }
    public static bool operator!=(Point p1, Point p2) {
        return p1.x != p2.x || p1.y != p2.y;
    }
}

class Program {
    static void Main() {
        Point p1 = new Point(1, 1);
        Point p2 = p1;
        Point p3 = new Point(1, 1);
        
        // 방법1. == 연산자 사용
        // 기본 동작 : 참조(주소)가 동일한가 ?
        Console.WirteLine(p1 == p2);  // true
        Console.WriteLine(p1 == p3);  // true
        
        // 방법2. Equals() 가상함수 사용
        // 기본 동작 : 참조가 동일한가 ?
        Console.WriteLine(p1.Equals(p2));  // true
        Console.WriteLine(p1.Equals(p3));  // false
    }
}

 

== 연산자와 같이 동등연산자로 만들면 같지 않을 경우인 !=연산자도 만들어야 한다.

 ② ==연산자

    => 참조(주소)가 동일한가를 조사

    => 연산자 재정의 문법으로 기본 동작 변경 가능. 기반 클래스 타입 참조를 사용할 경우 문제.

 

 ③ Equals 가상 메소드

    => 참조(주소)가 동일한가를 조사

    => 재정의 해서 객체의 상태 동일 여부로 구현하는 경우가 많음.

 


2. 값 타입(value type)의 동등성(Equality)

using System;

struct Point {
    private int x = 0;
    private int y = 0;
    
    public Point(int xPos, int yPos) {
        x = xPos;
        y = yPos;
    }
}

class Program {
    static void Main() {
        Point p1 = new Point(1, 1);
        Point p2 = p1;
        
        // 방법1. == 연산자 사용
        // 기본적으로 제공 안됨. => 연산자 재정의로 사용 가능
        Console.WirteLine(p1 == p2); // error
        
        // 방법2. Equals() 가상함수 사용
        // 객체에 대한 모든 메모리 조사
        Console.WriteLine(p1.Equals(p2));  // true
    }
}

 

이번엔 값 타입의 조사를 하기 위해 class를 struct로 바꾸었다.
먼저 그림으로 보면 아래와 같다.

 ① == 연산자

    => 제공 되지 않음.

    => 연산자 재정의 문법으로 제공 가능.

 

using System;

struct Point {
    private int x = 0;
    private int y = 0;
    
    public Point(int xPos, int yPos) {
        x = xPos;
        y = yPos;
    }
    
    public override bool Equals(Object obj) {
        Point pt = (Point)obj;
        return x == pt.x
    }
}

class Program {
    static void Main() {
        Point p1 = new Point(1, 1);
        Point p2 = p1;
        p2.y = 2;
        
        // 비교 정책 변경 - x만 조사하여 같은 경우 true 반환
        Console.WriteLine(p1.Equals(p2));  // true
    }
}

 

 ② Equals 가상 메소드

    => 메모리 내용을 비교

    => 재정의 해서 비교 정책을 변경가능

728x90
반응형