System.Object
C#에 존재하는 모든 클래스들은 상속받는다고 쓰지 않아도 Object 타입에 상속을 받고 있다.
모든 타입의 조상. 모든 값타입(int, double 등등) 참조 형식(enum, struct) 등이 Object 클래스를 상속 받는다.
이 Object 타입은 4개의 메서드를 가지고 있다. ToString, GetType, Equals, GetHashCode 가 4가지 메서드이다.
예제) C가 B를 상속받고 B가 A를 상속받을때 각각 객체 참조변수가 가리킬 수 있는 객체의 개수
class A
{ }
class B : A
{ }
class C : B
{ }
class Program
{
static void Main(string[] args)
{
A aObj = new A();
B bObj = new B();
C cObj = new C();
A aRef;
B bRef;
C cRef;
//퀴즈 1 : aRef가 가리킬 수 있는 객체는 모두 몇 개인가? 3개
aRef = aObj;
aRef = bObj;
aRef = cObj;
//퀴즈 2 : bRef가 가리킬 수 있는 객체는 모두 몇 개인가? 2개
bRef = bObj;
bRef = cObj;
//퀴즈 3 : cRef가 가리킬 수 있는 객체는 모두 몇 개인가? 1개
cRef = cObj;
//오브젝트 클래스는 다 가리킬 수 있다. 3개를 다 가리킬수있다.
Object oRef;
oRef = aObj;
oRef = bObj;
oRef = cObj;
}
}
A는 B와C를 자녀 클래스로 두고 있어서 ABC 객체 모두를 가리킬수 있다.
B는 C를 자녀클래스로 두고 있어서 BC만 가리킬 수 있고
C는 자기 자신만 가리킬수 있다.
Object는 모든 클래스의 부모클래스 이므로 ABC를 가리킬 수 있다.
ToString
해당 인스턴스가 속한 클래스의 전체 이름을 반환한다.
값타입에서 사용하면 해당타입이 담고있는 값을 반환한다.
예제) 위 소스의 aObj, bObj, cObj ToString() 해보기
Console.WriteLine(cObj.ToString());
Console.WriteLine(aObj.ToString());
Console.WriteLine(bObj.ToString());
namespace이름.클래스이름
이 출력되었다. Program 클래스 안에 있었다면
_20200602_001.Program.C
_20200602_001.Program.A
_20200602_001.Program.B
가 출력되었을 것이다
예제) 값타입에 ToString() 써보기
int n = 500;
double d = 3.1415926535897932384626;
string txt = "Hello: ";
Console.WriteLine(txt + n.ToString());
Console.WriteLine(txt + d.ToString());
txt = d.ToString();
Console.WriteLine(txt);
값타입에 쓰면 해당타입의 값을 반환한다.
GetType
클래스로 타입을 정의하면 (Type type = 클래스명.GetType())
해당 class의 타입정보를 가지고 있는 System.Type의 인스턴스를 보유하게 되고 이걸 GetType 메서드로 가져올 수 있음.
값타입에서 선언되었다면 클래스에 대해 타입의 전체 이름을 반환한다.
예제) GetType으로 클래스의 인스턴스 가져오기
Type type = cObj.GetType(); // GetType의 반환객체는 Type이다.
Console.WriteLine(type.FullName);
Console.WriteLine(type.IsClass);
Console.WriteLine(type.IsArray);
위에서 썻던 C클래스에 GetType()을 한것이다.
FullName은 ToString 같이 namespace와 클래스명이 출력되었고
IsClass는 GetType으로 반환된 객체 type이 클래스이냐? 참이면 True, 거짓이면 False를 반환한다.
IsArray도 마찬가지로 type이 Array이면 참 True, 거짓이면 False를 반환한다.
예제) int와 string 변수에 GetType() 써보기
int n = 5;
int n2 = 5;
string txt = "text";
Type intType = n.GetType();
Console.WriteLine(intType.FullName);
Console.WriteLine(txt.GetType().FullName);
Equals
Equals도 값 형식에 썼는지 참조 형식에 썼는지에 따라 다르다.
참조형식.Equals(참조형식) 에 사용할 경우 할당된 메모리 위치를 가리키는 식별자의 값이 같은지 비교한다.
값형식.Equals(값형식)에 사용할 경우 변수가 가리키는 값 자체를 반환하므로 결괏값끼리 같은지 비교한다.
만약 Book 클래스로 new를 이용해 b1, b2 객체를 생성했다고 생각해보자.
예제) Book클래스로 b1 b2 객체를 생성해서 Equals() 해보기
class Book
{
decimal _isbn;
public Book(Decimal isbn)
{
_isbn = isbn;
}
}
Book b1 = new Book(9788998139018);
Book b2 = new Book(9788998139018);
Book b3 = b1;
Console.WriteLine("Book클래스 b1과 b3객체는 같은가 : " + b1.Equals(b3));
// 데이터주소를 가리키는 스택변수의 값을 서로 비교 False 반환
False가 나올것이다. new Book으로 생성된 힙메모리의 위치가 다르기 때문이다.
예제) 값타입으로 Equals() 해보기
string aString1 = "test";
string aString2 = "test";
string aString3 = aString1; // 1,2,3은 같은곳에 있는 "test"를 가리킨다.
if (aString1.Equals(aString2))
{
Console.WriteLine("스트링1과 2는 참");
}
if (aString1.Equals(aString3))
{
Console.WriteLine("스트링1과 3은 참");
}
if (aString2.Equals(aString3))
{
Console.WriteLine("스트링2와 3은 참");
}
모두 True가 나오게 된다. aString1,2,3가 소유하는 값을 대상으로 비교한다.
GetHashCode
특정 인스턴스를 고유하게 식별할 수있는 4바이트 int값을 반환한다.
Equals의 반환값이 True인 객체라면 서로 같음을 의미하고 그 객체들을 식별하는 고윳값 또한 같다.
int값을 반환하므로 int값을 넘어서는 값을 GetHashCode 했을 경우
다른 값인데도 같은 해시코드를 생성하는 해시 충돌(Hash Collision)이 발생할 수 있다.
이럴경우 다시한번 Equals()를 호출해서 동일한지 판단할 수 있는 기회가 생긴다.
예제)
Book b1 = new Book(9788998139018);
Book b2 = new Book(9788998139018);
short n1 = 256;
short n2 = 32750;
short n3 = 256;
Console.WriteLine(n1.GetHashCode());
Console.WriteLine(n2.GetHashCode());
Console.WriteLine(n3.GetHashCode());
Console.WriteLine("북클래스 b1과 b2의 해쉬코드");
Console.WriteLine(b1.GetHashCode());
Console.WriteLine(b2.GetHashCode());
'컴퓨터 > C#' 카테고리의 다른 글
[C#] this (0) | 2020.06.02 |
---|---|
[C#] Array 타입 (0) | 2020.06.02 |
[C#] 캡슐화, 상속 (0) | 2020.06.01 |
[C#] Main문 매개변수 args 사용해보기, ERRORLEVEL 환경변수로 return값 확인 (0) | 2020.05.31 |
[C#] 종료자, 정적멤버와 인스턴스멤버, 정적 메서드, 접근제한자, 싱글톤 (0) | 2020.05.29 |