구조체(struct)
구조체는 struct 키워드를 사용하여 값 형식(Value Types)을 정의하고 클래스는 class 키워드를 사용하여 참조 형식(Reference Types)을 정의합니다.
값 형식(Value Types)
값이 스택(Stack) 영역에 할당됩니다.
참조 형식(Referenct Types)
값이 힙(Heap) 영역에 할당됩니다.
스택(Stack) 영역은 값이 할당된 힙의 메모리 주소를 참조합니다.
구조체 정의
struct 키워드를 사용하여 구조체를 정의합니다.
struct Person
{
public string name;
public int age;
}
Person 구조체 내부에는 name과 age라는 필드가 존재합니다. 구조체에는 변수뿐만 아니라 메서드, 인덱서도 존재할 수 있습니다.
구조체 변수
클래스의 인스턴스를 생성하듯이 구조체도 변수를 생성해야 합니다. 다음 예제는 구조체 변수를 생성하고 구조체 멤버를 접근합니다.
struct Person
{
public string name;
public int age;
public void displayField()
{
Console.WriteLine("name: " + name + " / age: " + age);
}
}
class Program
{
static void Main(string[] args)
{
// 구조체 변수 선언
Person person;
// 구조체 변수 필드에 값 할당
person.name = "둘리";
person.age = 999;
// 구조체 변수 필드 호출
Console.WriteLine("Person.name: " + person.name);
Console.WriteLine("Person.age: " + person.age);
person.displayField();
}
실행 결과
Person.name: 둘리
Person.age: 999
name: 둘리 / age: 999
구조체도 new 키워드를 사용하여 인스턴스화 가능합니다. new 키워드를 사용하는 경우 매개변수가 없는 생성자를 호출하고 모든 멤버를 기본 값(Default Value)으로 초기화합니다.
struct Person
{
public string name;
public int age;
public void displayField()
{
Console.WriteLine("name: " + name + " / age: " + age);
}
}
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.displayField();
}
}
실행 결과
name: / age: 0
name은 string타입이므로 ""으로 초기화되고 age는 int타입이므로 0으로 초기화됩니다.
구조체 생성자
클래스처럼 생성자를 만들 수 있습니다.
struct Person
{
public string name;
public int age;
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
public void displayField()
{
Console.WriteLine("name: " + name + " / age: " + age);
}
}
class Program
{
static void Main(string[] args)
{
Person person = new Person("마이콜", 20);
person.displayField();
}
}
실행 결과
name: 마이콜 / age: 20
구조체 생성자의 단점은 모든 필드에 값을 할당해야 한다는 것입니다.
struct Person
{
public string name;
public int age;
public Person(string name)
{
this.name = name;
}
}
위 예제는 생성자에서 age 필드에 값이 할당되지 않았으므로 컴파일 에러가 발생합니다.
컴파일 에러를 해결하기 위해서는 다음 예제처럼 모든 생성자에서 모든 필드의 값을 할당해야 합니다.
struct Person
{
public string name;
public int age;
public string address;
public Person(string name)
{
this.name = name;
this.age = 0;
this.address = "";
}
public Person(string name, int age)
{
this.name = name;
this.age = age;
this.address = "";
}
public Person(string name, int age, string address)
{
this.name = name;
this.age = age;
this.address = address;
}
}
추가적으로 C# 9.0 이하 버전에서는 매개변수가 없는 생성자를 만들 수 없습니다.
구조체 프로퍼티
구조체에서 프로퍼티를 사용할 수 있습니다. 다음 예제는 구조체 필드를 private로 선언 후 필드를 프로퍼티로 접근합니다.
struct Person
{
private string name;
private int age;
public string Name
{
get { return name; }
set { name = value;}
}
public int Age
{
get { return age; }
set { age = value; }
}
}
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Name = "고길동";
person.Age = 50;
Console.WriteLine("Name: " + person.Name + " / Age: " + person.Age);
}
}
실행 결과
Name: 고길동 / Age: 50
클래스와 차이점
구조체는 클래스와 유사하게 보이지만, 몇 가지 차이점이 존재합니다. 다음 예제는 클래스와 구조체의 주요 차이점인 값 형식과 참조 형식에 대해 설명합니다.
먼저, 클래스입니다.
class Person
{
public string name;
}
class Program
{
static void Main(string[] args)
{
Person person1 = new Person();
person1.name = "둘리";
// person1을 person2에 할당합니다.
Person person2 = person1;
person2.name = "마이콜";
// person1.name의 값도 변경되었습니다.
Console.WriteLine("person1.name: " + person1.name);
Console.WriteLine("person2.name: " + person2.name);
}
}
실행 결과
person1.name: 마이콜
person2.name: 마이콜
위 예제에서 person1을 person2에 할당했습니다. 클래스는 참조 형식이므로 person2와 person1은 동일한 객체를 참조합니다. 따라서 person2의 값이 변경되면 person1의 값도 변경됩니다.
클래스와 반대로 구조체는 값이 변경되지 않습니다.
struct Person
{
public string name;
}
class Program
{
static void Main(string[] args)
{
Person person1 = new Person();
person1.name = "둘리";
Person person2 = person1;
person2.name = "마이콜";
Console.WriteLine("person1.name: " + person1.name);
Console.WriteLine("person2.name: " + person2.name);
}
}
실행 결과
person1.name: 둘리
person2.name: 마이콜
구조체는 값 형식이므로 person2의 값을 변경해도 person1에 영향을 미치지 않습니다.
정리
- 구조체는 값 형식, 클래스는 참조 형식입니다.
- 구조체 생성자 내부에서 모든 필드의 값을 할당해야 합니다.
- 구조체는 상속이 불가능합니다.
'C#' 카테고리의 다른 글
[C#]가상 메서드(Virtual Method), Virtual 키워드 (0) | 2022.05.16 |
---|---|
[C#]봉인 클래스(Sealed Class) 및 봉인 메서드(Sealed Class) (0) | 2022.05.15 |
[C#]this 키워드 (0) | 2022.05.09 |
[C#]접근 제한자(Access Modifier) - public, private, protected (0) | 2022.05.08 |
[C#]정적 생성자(Static Constructor) (0) | 2022.05.05 |
댓글