1-1) 같음 연산자 '=='
연산자 왼쪽 오른쪽에 오는 것들이 같은지를 판단하는 연산자다
값 타입의 경우 좌 우의 값이 같으면 True, 다르면 False 를 반환한다.
참조 타입은 좌 우 객체가 같은지를 비교한다.
(객체 내부의 값이 같은지 비교 한다는 뜻, 참조(주소)는 상관없음)
1-2) Equals 도 똑같이 == 과 동일한 역할
public virtual bool Equals(object? obj)
public virtual bool Equals(object? objA, object? objB)
Equals 메서드는 기본적으로 객체가 같은지를 비교한다. 기본적으로는 == 과 동일한 작동한다.
값 타입은 값이 같은지 비교를 하고 참조 타입은 객체가 같은지를 비교한다.
(객체 내부의 값이 같은지 비교 한다는 뜻, 참조(주소)는 상관없음)
object 클래스의 Equals 를 보면 내부적으로 == 으로 비교하고 있는 것을 알 수 있다.
C#에서 기본적으로 정의된 Equals 는 == 과 동일한 작동을 한다. 하지만 Equals를 보면 virtual 키워드가 있는것을 알 수 있다. 이것은 사용자(프로그래머)가 언제 어디서는 해당 메서드를 재정의(override)해서 사용할 수 있다는 뜻이다. 그렇기 때문에 "Equals 메서드는 기본적으로 == 과 동일한 역할을 하지만, 재정의에 따라서 어떤 동작을 할지 확신할 수는 없다."
1-3) ReferenceEqual 메서드
public static bool ReferenceEquals(object? objA, object? objB)
첫번째 두번째 매개변수로는 비교하고자 하는 객체를 넣는다. 두 객체의 참조가 같으면 True, 다르면 False 를 반환한다.
ReferenceEquals는 진짜 해당 참조를 비교하는 메서드 (주소 비교)
Equals는 클래스 등에서 사용할때 Equals 를 각 클래스에 맞게 오버라이딩 해서 사용해야 하지만 ReferenceEquals는 오버라이딩 할 수 없다. 그러니, 참조가 같은지 (주소가 같은지)를 비교할때는 이 ReferenceEquals를 사용하면 된다.
ReferenceEquals는 "참조(가리키는 주소)"가 같은지 확인하는 것 이기 때문에 값타입 비교는 항상 False 가 나오게 된다.
2-1) 값 타입
using System;
public static void Main(string[] args)
{
int a = 10;
int b = 10;
int c = a;
// a, b, c 모두 "BlockDMask" 문자열을 가지고 있지만.
// a, c 가 같은 객체를 가리키고 있고(참조가 같음)
// b만 다른 객체를 가리키고 있다.(참조가 다름)
Console.WriteLine($"a : {a}, {a.GetTypeCode()}");
Console.WriteLine($"b : {b}, {b.GetTypeCode()}");
Console.WriteLine($"c : {c}, {c.GetTypeCode()}");
// == 비교 (객체 내부 값이 같은지)
Console.WriteLine("\n1. == 비교");
Console.WriteLine($"a == b : {a == b}");
Console.WriteLine($"b == c : {b == c}");
Console.WriteLine($"c == a : {c == a}");
// Equals 비교 (override에 따라 다르지만, string 은 객체 내부 값 같은지)
Console.WriteLine("\n2. Equals 비교");
Console.WriteLine($"a.Equals(b) : {a.Equals(b)}");
Console.WriteLine($"b.Equals(c) : {b.Equals(c)}");
Console.WriteLine($"c.Equals(a) : {c.Equals(a)}");
// ReferenceEquals 비교 (참조가 같은지, 값 타입에서는 의미 없음...... 쓰지말것)
Console.WriteLine("\n3. ReferenceEquals 비교");
Console.WriteLine($"object.ReferenceEqual(a, b) : {ReferenceEquals(a, b)}");
Console.WriteLine($"object.ReferenceEqual(b, c) : {ReferenceEquals(b, c)}");
Console.WriteLine($"object.ReferenceEqual(c, a) : {ReferenceEquals(c, a)}");
}
값 타입을 보면 == , Equals 둘다 동일하게 그리고 당연하게 값을 비교 하게 된다. 반면 ReferenceEquals 에서는 모두 False 가 나오게 된다. 값 타입에서는 ReferenceEquals는 무의미한 메서드다.
2-2) 참조 타입
using System;
public static void Main(string[] args)
{
string a = "BlockDMask";
string b = "Block";
b += "DMask";
string c = a; // c와 a 는 같은 참조
// a, b, c 모두 "BlockDMask" 문자열을 가지고 있지만.
// a, c 가 같은 객체를 가리키고 있고(참조가 같음)
// b만 다른 객체를 가리키고 있다.(참조가 다름)
Console.WriteLine($"a : {a}, {a.GetTypeCode()}");
Console.WriteLine($"b : {b}, {b.GetTypeCode()}");
Console.WriteLine($"c : {c}, {c.GetTypeCode()}");
// == 비교 (객체 내부 값이 같은지)
Console.WriteLine("\n1. == 비교");
Console.WriteLine($"a == b : {a == b}");
Console.WriteLine($"b == c : {b == c}");
Console.WriteLine($"c == a : {c == a}");
// Equals 비교 (override에 따라 다르지만, string 은 객체 내부 값 같은지)
Console.WriteLine("\n2. Equals 비교");
Console.WriteLine($"a.Equals(b) : {a.Equals(b)}");
Console.WriteLine($"b.Equals(c) : {b.Equals(c)}");
Console.WriteLine($"c.Equals(a) : {c.Equals(a)}");
// ReferenceEquals 비교 (참조가 같은지)
Console.WriteLine("\n3. ReferenceEquals 비교");
Console.WriteLine($"object.ReferenceEqual(a, b) : {ReferenceEquals(a, b)}");
Console.WriteLine($"object.ReferenceEqual(b, c) : {ReferenceEquals(b, c)}");
Console.WriteLine($"object.ReferenceEqual(c, a) : {ReferenceEquals(c, a)}");
}
a, b, c 문자열을 각각 생성해봤는데 a와 c는 참조도 같고 값도 같은 문자열이고 b는 참조가 a,c랑 다르지만, 값은 같은 문자열이다. (b를 저렇게 선언한 이유는 C# 단에서"BlockDMask"를 동일하게 선언하는 경우 최적화를 통해서 동일한 참조를 가리킬 수 있기 때문이다.
'프로그래밍 언어 > C#' 카테고리의 다른 글
C# 각 타입별로 접근제한자 (Access Modifiers) (0) | 2023.06.26 |
---|---|
C# 문자열 배열을 int 배열로 변환 (0) | 2023.06.16 |
C# 복사본 만들기 (0) | 2023.06.13 |
C# 문자열 자르기(Split), 추출(Substring) (0) | 2023.06.13 |
C# 문자열 공백 기준으로 분할 (0) | 2023.06.13 |