클래스 생성자 만들기 및 개체 인스턴스화
클래스 속성 및 메서드 외에도 클래스 정의에는 새 개체(클래스 인스턴스)를 초기화하는 데 사용되는 생성자가 포함됩니다.
클래스 생성자
클래스 생성자는 형식과 이름이 같은 메서드입니다(생성자 메서드는 클래스와 동일한 이름을 사용).
클래스 생성자에는 다음 두 가지 유형이 있습니다.
- 인스턴스 생성자입니다. 인스턴스 생성자는 개체를 만들 때 인스턴스 필드 변수를 만들고 초기화하는 데 사용됩니다.
- 정적 생성자입니다. 정적 생성자는 정적 데이터를 초기화하거나 한 번만 수행해야 하는 특정 작업을 수행하는 데 사용됩니다. 정적 생성자는 첫 번째 인스턴스를 만들거나 정적 멤버를 참조하기 전에 자동으로 호출됩니다.
클래스 생성자는 기본적으로 인스턴스 생성자입니다.
인스턴스 생성자 구문
인스턴스 생성자는 클래스와 동일한 이름을 사용하여 선언되며 반환 형식을 포함하지 않습니다. 생성자의 메서드 서명에는 선택적 액세스 한정자, 메서드 이름 및 해당 매개 변수 목록이 포함될 수 있습니다. 생성자의 메서드 서명에는 반환 형식이 포함되지 않습니다.
다음 예제에서는 Person클래스에 대한 간단한 생성자를 보여줍니다.
public class Person
{
public Person()
{
// Field initialization and constructor logic goes here.
}
// Remaining implementation of Person class.
}
클래스에는 둘 이상의 생성자가 있을 수 있습니다. 클래스에 둘 이상의 생성자가 있는 경우 생성자는 일반적으로 다른 인수를 사용합니다.
다음 예제에서는 두 개의 생성자가 있는 Person이라는 클래스를 보여줍니다.
public class Person
{
public Person()
{
// Field initialization and constructor logic goes here.
string name = "Person One";
Console.WriteLine($"Person created: {name}");
}
public Person(string fName, string lName)
{
string name = fName + " " + lName;
Console.WriteLine($"Person created: {name}");
}
// Remaining implementation of Person class.
}
클래스 생성자를 사용하여 개체 인스턴스화
new 키워드를 사용하여 개체를 인스턴스화하면 .NET 런타임은 클래스 정의에서 연결된 인스턴스 생성자를 호출하고 개체에 대한 메모리를 할당합니다.
다음 코드 조각에서 Person 클래스는 간단한 인스턴스 생성자를 정의합니다.
Program 클래스에는 Main 연산자를 사용하여 newPerson 인스턴스를 만드는 person1 메서드가 포함되어 있습니다. 런타임은 새 개체에 대한 메모리가 할당된 직후에 Person 생성자를 호출합니다.
public class Person
{
public Person()
{
// Field initialization and constructor logic goes here.
}
}
static class Program
{
// the Main method is the entry point of the program.
static void Main()
{
Person person1 = new Person();
}
}
매개 변수를 사용 및 사용하지 않는 생성자
매개 변수를 사용하지 않는 생성자를 매개 변수 없는 생성자라고 합니다. 런타임은 new 연산자를 사용하여 개체가 인스턴스화되고 생성자에 인수가 제공되지 않을 때 매개 변수가 없는 생성자를 호출합니다.
메모
클래스가 정적이지 않은 경우 클래스 인스턴스화를 사용하도록 설정하기 위해 생성자가 없는 클래스에는 C# 컴파일러에 의해 공용 매개 변수가 없는 생성자가 제공됩니다.
클래스는 종종 매개 변수를 사용하는 생성자를 정의합니다. 매개 변수를 사용하는 생성자는 new 연산자 또는 기본 문을 사용하여 호출해야 합니다. 클래스는 하나 이상의 생성자를 정의할 수 있습니다.
다음 코드 조각은 3개의 생성자가 있는 Person이라는 클래스를 보여줍니다.
public class Person
{
public Person()
{
// Field initialization and constructor logic goes here.
Console.WriteLine("An instance of the Person class is being instantiated without name or age parameters.");
}
public Person(string name)
{
// Field initialization and constructor logic goes here.
Console.WriteLine($"An instance of the Person class is being instantiated using a name ({name}) parameter.");
}
public Person(string name, int age)
{
// Field initialization and constructor logic goes here.
Console.WriteLine($"An instance of the Person class is being instantiated using name ({name}) and age ({age}) parameters.");
}
}
static class Program
{
// the Main method is the entry point of the program.
static void Main()
{
Person person1 = new Person();
Person person2 = new Person("Person Two");
Person person3 = new Person("Person Three", 30);
}
}
생성자가 없는 클래스
클래스에 명시적 인스턴스 생성자가 없는 경우 C#은 다음 예제와 같이 해당 클래스의 인스턴스를 인스턴스화하는 데 사용할 수 있는 매개 변수가 없는 생성자를 제공합니다.
public class Person
{
public int age;
public string name = "unknown";
}
class Example
{
static void Main()
{
var person = new Person();
Console.WriteLine($"Name: {person.name}, Age: {person.age}");
// Output: Name: unknown, Age: 0
}
}
이 생성자는 해당 이니셜라이저에 따라 인스턴스 필드 및 속성을 초기화합니다. 필드 또는 속성에 이니셜라이저가 없는 경우 해당 값은 필드 또는 속성 형식의 기본값으로 설정됩니다. 클래스에서 하나 이상의 인스턴스 생성자를 선언하는 경우 C#은 매개 변수가 없는 생성자를 제공하지 않습니다.
생성자 매개 변수를 사용하여 클래스 데이터 초기화
생성자에 전달된 매개 변수는 생성자에 로컬입니다. 매개 변수는 종종 클래스의 데이터 필드를 초기화하는 데 사용됩니다.
다음 코드 조각은 Person 및 personName 필드를 초기화하는 생성자가 있는 personAge이라는 클래스를 보여줍니다.
public class Person
{
public string personName;
public string personAge;
public Person()
{
// Field initialization and constructor logic goes here.
personName = "unknown";
personAge = "unknown";
}
public Person(string name)
{
// Field initialization and constructor logic goes here.
personName = name;
personAge = "unknown";
}
public Person(string name, int age)
{
// Field initialization and constructor logic goes here.
personName = name;
personAge = age.ToString();
}
}
static class Program
{
// the Main method is the entry point of the program.
static void Main()
{
Person person1 = new Person();
Person person2 = new Person("Person Two");
Person person3 = new Person("Person Three", 30);
Console.WriteLine($"Person 1 Name: {person1.personName} Age: {person1.personAge}");
Console.WriteLine($"Person 2 Name: {person2.personName} Age: {person2.personAge}");
Console.WriteLine($"Person 3 Name: {person3.personName} Age: {person3.personAge}");
}
}
앞의 예제에서 Person 클래스는 세 개의 생성자로 정의됩니다. 첫 번째 생성자는 personName 및 personAge 필드를 초기화하여 "unknown". 두 번째 생성자는 personName 필드를 name 매개 변수에 전달된 값으로 초기화하고 personAge"unknown" 필드를 초기화합니다. 세 번째 생성자는 personName 및 personAge 필드를 각각 name 및 age 매개 변수에 전달된 값으로 초기화합니다.
필드는 공용이므로 Main 메서드에서 직접 액세스할 수 있습니다. 코드가 실행되면 다음 출력이 생성됩니다.
Person 1 Name: unknown Age: unknown
Person 2 Name: Person Two Age: unknown
Person 3 Name: Person Three Age: 30
식 본문 정의
생성자를 단일 문으로 구현할 수 있는 경우 식 본문 정의 사용하여 생성자가 구현될 때 클래스 멤버에 매개 변수를 할당할 수 있습니다.
예를 들어 다음 생성자는 modelName 매개 변수에 전달된 값을 사용하여 model 필드를 초기화합니다.
public class Car
{
public string modelName;
public Car(string model) => modelName = model;
}
Car 클래스에는 modelName형식인 string하나의 공용 필드가 있습니다.
modelName 필드는 자동차 모델의 이름을 저장하기 위한 것입니다.
Car 클래스에는 model라는 단일 문자열 매개 변수를 사용하는 생성자도 포함됩니다. 생성자는 식 본문 정의(=> 구문으로 표시됨)를 사용하여 modelName 매개 변수에 전달된 값으로 model 필드를 초기화합니다. 즉, 새 Car 개체가 인스턴스화되면 modelName 필드가 생성자에 대한 인수로 제공된 값으로 설정됩니다.
식이라는 용어에서 알 수 있듯이 => 연산자의 오른쪽은 식이며 단순 할당 문으로 제한되지 않습니다. 식은 값을 반환하는 유효한 C# 식일 수 있습니다.
다음 코드 조각은 간단한 계산을 수행하는 식 본문 정의를 구현하는 방법을 보여 줍니다.
public class Employee
{
public int Salary;
public Employee() { }
public Employee(int annualSalary) => Salary = annualSalary;
public Employee(int weeklySalary, int numberOfWeeks) => Salary = weeklySalary * numberOfWeeks;
}
이 클래스는 다음 문 중 하나를 사용하여 만들 수 있습니다.
Employee e1 = new Employee(30000);
Employee e2 = new Employee(500, 52);
정적 생성자
정적 생성자는 정적 데이터를 초기화하거나 한 번만 수행해야 하는 특정 작업을 수행하는 데 사용됩니다. 첫 번째 인스턴스를 만들거나 정적 멤버를 참조하기 전에 자동으로 호출됩니다. 정적 생성자는 최대 한 번 호출됩니다.
다음 코드 조각은 정적 필드 및 정적 생성자를 구현하는 Person 클래스의 업데이트된 버전을 보여 줍니다.
public class Person
{
public string personName;
public string personAge;
// Static field
public static string defaultName;
public static string defaultAge;
// Static constructor
static Person()
{
// Static field initialization
defaultName = "unknown";
defaultAge = "unknown";
}
public Person()
{
// Field initialization and constructor logic goes here.
personName = defaultName;
personAge = defaultAge;
}
public Person(string name)
{
// Field initialization and constructor logic goes here.
personName = name;
personAge = defaultAge;
}
public Person(string name, int age)
{
// Field initialization and constructor logic goes here.
personName = name;
personAge = age.ToString();
}
}
업데이트된 Person 클래스에는 personName 및 personAge두 개의 인스턴스 필드가 있으며 둘 다 string형식입니다. 이러한 필드는 각각 사람의 이름과 나이를 저장합니다.
또한 클래스는 defaultName형식의 두 정적 필드(defaultAge 및 string)를 정의합니다. 정적 필드는 클래스의 모든 인스턴스 간에 공유되며 한 번만 초기화됩니다. 이 경우 정적 필드는 personName 및 personAge 필드에 대한 기본값을 제공하는 데 사용됩니다.
정적 생성자 static Person() 정적 필드 초기화를 담당합니다.
defaultName
"unknown" 설정하고 defaultAge"unknown" 설정합니다. 정적 생성자는 클래스의 인스턴스를 만들거나 정적 멤버에 액세스하기 전에 자동으로 호출됩니다.
Person 클래스에는 세 개의 인스턴스 생성자가 포함됩니다.
매개 변수가 없는 생성자는 public Person()personName 및 personAge 필드를 defaultNamedefaultAge정적 필드 값을 사용하여 초기화합니다. 즉, Person 개체를 만들 때 인수가 제공되지 않으면 "unknown" 기본값이 이름과 나이 모두에 사용됩니다.
생성자 public Person(string name)name단일 매개 변수를 사용하고 이 값을 사용하여 personName 필드를 초기화합니다.
personAge 필드는 정적 필드 defaultAge값으로 초기화됩니다. 이 생성자를 사용하면 기본 사용 기간을 사용하는 동안 지정된 이름의 Person 개체를 만들 수 있습니다.
생성자 public Person(string name, int age)name 및 age두 개의 매개 변수를 사용합니다.
personName 매개 변수의 값과 age 매개 변수의 문자열 표현을 사용하여 name 필드를 사용하여 personAge 필드를 초기화합니다. 이 생성자를 사용하면 지정된 Personname둘 다 사용하여 age 개체를 만들 수 있습니다.
정적 생성자의 속성
정적 생성자에는 다음과 같은 속성이 있습니다.
정적 생성자는 액세스 한정자를 사용하거나 매개 변수를 포함하지 않습니다.
클래스에는 정적 생성자가 하나만 있을 수 있습니다.
정적 생성자는 상속되거나 오버로드될 수 없습니다.
정적 생성자는 직접 호출할 수 없으며 CLR(공용 언어 런타임)에서만 호출됩니다. 자동으로 호출됩니다.
사용자는 프로그램에서 정적 생성자가 실행되는 시기를 제어할 수 없습니다.
정적 생성자가 자동으로 호출됩니다. 첫 번째 인스턴스를 만들거나 해당 클래스에 선언된 정적 멤버(기본 클래스 아님)를 참조하기 전에 클래스를 초기화합니다. 정적 생성자는 인스턴스 생성자 전에 실행됩니다. 정적 필드 변수 이니셜라이저가 정적 생성자의 클래스에 있는 경우 클래스 선언에 나타나는 텍스트 순서로 실행됩니다. 이니셜라이저는 정적 생성자 바로 앞에서 실행됩니다.
정적 필드를 초기화하는 정적 생성자를 제공하지 않으면 모든 정적 필드가 기본값으로 초기화됩니다.
정적 생성자가 예외를 throw하는 경우 런타임은 예외를 두 번째로 호출하지 않으며 형식은 애플리케이션 도메인의 수명 동안 초기화되지 않은 상태로 유지됩니다. 가장 일반적으로 정적 생성자가 형식을 인스턴스화할 수 없거나 정적 생성자 내에서 발생하는 처리되지 않은 예외에 대해
TypeInitializationException예외가 throw됩니다. 소스 코드에 명시적으로 정의되지 않은 정적 생성자의 경우 문제 해결을 위해 IL(중간 언어) 코드를 검사해야 할 수 있습니다.정적 생성자가 있으면
BeforeFieldInit형식 특성이 추가되지 않습니다. 이렇게 하면 런타임 최적화가 제한됩니다.static readonly선언된 필드는 선언의 일부 또는 정적 생성자에서만 할당할 수 있습니다. 명시적 정적 생성자가 필요하지 않은 경우 더 나은 런타임 최적화를 위해 정적 생성자를 통해서가 아니라 선언 시 정적 필드를 초기화합니다.런타임은 단일 애플리케이션 도메인에서 정적 생성자를 두 번 이상 호출하지 않습니다. 이 호출은 클래스의 특정 형식에 따라 잠긴 지역에서 이루어집니다. 정적 생성자의 본문에는 추가 잠금 메커니즘이 필요하지 않습니다.
메모
직접 액세스할 수는 없지만 초기화 예외 문제 해결을 지원하기 위해 명시적 정적 생성자의 존재를 문서화해야 합니다.