클래스의 구성 요소 중엔 생성자(constructor)라는 메서드가 있다.
개체를 생성하면서 무엇인가를 하고자 할 때 사용되는 메서드.
일반적으로 생성자는 개체를 초기화하는 데 사용됨.
생성자 이름은 클래스 이름과 동일함.
클래스의 인스턴스가 생성될 때 자동으로 생성자가 실행된다.
클래스에 매개변수를 달리하여 생성자를 여러 개 만들 수도 있음.
생성자도 오버로드가 가능함.
this 키워드를 사용해서 다른 생성자를 호출할 수도 있음.
class ConstructorDemo
{
public ConstructorDemo()
{
Console.WriteLine("생성자 호출");
}
static void Main()
{
ConstructorDemo c = new ConstructorDemo();
}
}
namespace ConstructorParameter
{
class My
{
private string _name;
private int _age;
public My(string name, int age)
{
this._name = name;
this._age = age;
}
public void PrintMy()
{
Console.WriteLine($"이름 : {this._name}, 나이 : {this._age}");
}
}
class ConstructorParameter
{
static void Main()
{
My my = new My("백승수", 21);
my.PrintMy();
}
}
}
using System;
class Circle
{
private int _radius;
public Circle(int radius)
{
_radius = radius;
}
public double GetArea()
{
return Math.PI * _radius * _radius;
}
}
class GetCircleArea
{
static void Main()
{
Circle circle1 = new Circle(5);
Console.WriteLine(circle1.GetArea());
Circle circle2 = new Circle(10);
Console.WriteLine(circle2.GetArea());
}
}
클래스에는 매개변수를 달리하여 생성자를 여러 개 만들 수 있다. 이를 생성자 오버로드라 한다.
class ConstructorLog
{
public ConstructorLog()
{
Console.WriteLine("기본 생성자 실행");
}
public ConstructorLog(string message)
{
Console.WriteLine("오버로드된 생성자 실행 : " + message);
}
class ConstructorOverload
{
static void Main()
{
var log1 = new ConstructorLog();
var log2 = new ConstructorLog("C#");
var log3 = new ConstructorLog("ASP.NET");
}
}
}
클래스의 정적 멤버를 호출할 때 맨 먼저 호출되는 정적 생성자는 static으로 만들고,
인스턴스 생성자는 public 키워드로 만든다.
인스턴스를 생성할 수 없습니다. 정적 생성자는 인스턴스와 관계없이 클래스 레벨에서 단 한 번만 호출되므로, 인스턴스 생성자가 없으면 객체를 생성할 수 없습니다.
생성자에서 this()는 자신의 또 다른 생성자를 의미함.
this() 생성자로 매개변수가 있는 생성자에서
매개변수가 없는 생성자를 호출하거나
또 다른 생성자들을 호출할 수 있음.
> class Say
. {
. private string message = "[1] hello.";
. public Say() => Console.WriteLine(this.message);
.
. public Say(string message) : this()
. {
. this.message = message;
. Console.WriteLine(this.message);
. }
. }
> new Say("[2] byebye");
[1] hello.
[2] byebye
this() 호출 > this(string message) 호출
이런 순서로 가는 코드.
this() 생성자를 사용하면 생성자를 포워딩(forwarding)하여 다른 생성자에 값을 전달하기 좋다.
> class Money
. {
. public Money() : this(1000) { }
. public Money(int money) => Console.WriteLine("Money : {0:#,###}", money);
. }
> var basic = new Money();
Money : 1,000
> var bonus = new Money(2000);
Money : 2,000
기본 생성자에 있는 this(1000)가 인자 있는 다른 생성자를 호출하는 예시.
필드를 정의할 때 readonly 키워드를 붙여서 읽기 전용 필드를 만들 수 있다.
읽기 전용 필드는 클래스의 생성자로만 초기화가 가능하다.
상수는 선언과 동시에 반드시 초기화해야 에러가 발생하지 않지만,
읽기 전용 필드는 선언과 동시에 초기화도 가능하고 선언한 후 생성자로 초기화할 수도 있다.
소멸자는 클래스에서 인스턴스화된 개체가 메모리상에서 없어질 때 실행되는 메서드이다.
소멸자(destructor)는 종료자(finalizer)라고도 한다.
닷넷의 가비지 콜렉터에서 클래스의 인스턴스를 사용한 후 최종 정리할 때 실행되는 클래스에서
가장 늦게 호출되는 메서드이다.
클래스 이름과 동일한 메서드로 앞에 ~ 붙여서 만든다.
C# 에서는 모든 함수를 클래스 내에 선언하기 때문에,
함수 대신에 메서드라고 한다.
메서드는 개체가 수행할 수 있는 기능, 동작, 행위 등을 의미한다.
메서드 이름은 다음과 같이 동사+명사; 형태를 권장한다. ex. GetPrice(), SetPrice()
params 키워드를 붙인다. 가변 길이 매개변수는 매개변수를 선언할 때 반드시 마지막에 위치해야 함.void ModifyValue(int x)
{
x = 10; // x의 값만 변경됨
Console.WriteLine($"Inside Method: {x}");
}
int a = 5;
ModifyValue(a);
Console.WriteLine($"Outside Method: {a}");
그냥 변수 넣으면 메서드 안에서 해당 변수 조작 못한다
void ModifyRef(ref int x)
{
x = 10; // 원본 값 변경
Console.WriteLine($"Inside Method: {x}");
}
int a = 5;
ModifyRef(ref a);
Console.WriteLine($"Outside Method: {a}");
ref 붙여서 변수 넣으면 메서드 안에서 해당 변수 조작 가능하다.
포인터랑 비슷한듯?
void InitializeOut(out int x)
{
x = 10; // 반드시 초기화 필요
Console.WriteLine($"Inside Method: {x}");
}
int a; // 초기화하지 않음
InitializeOut(out a);
Console.WriteLine($"Outside Method: {a}");
메서드한테 해당 변수 초기화까지 맡겨버린다.
return은 반환을 하는거고, 이건 ref에 값 넣는 과정
ref: 메서드 호출 전에 반드시 변수 초기화해야 함.
out: 메서드 호출 전에 초기화 안 해도 되고, 메서드 내부에선 반드시 초기화해야 함.
ref: ref는 입력으로도 사용되기 때문에 기존 값을 변경할 수 있다는 의미를 가짐.
out: 출력 전용이므로 초기값은 중요하지 않고, 메서드 내부에서 값을 설정해서 반환하겠다는 의미를 가짐.
자료형.TryParse("변환할 내용", out "변환이 되면 담을 그릇")
if (DateTime.TryParse("2020-01-01", out var myDate))
{
Console.WriteLine(myDate);
}
class Program
{
// params 키워드를 사용한 메서드
static int AddNumbers(params int[] numbers)
{
int sum = 0;
foreach (int num in numbers)
{
sum += num;
}
return sum;
}
static void Main()
{
// 1. 개별적으로 값을 나열해서 전달
int result1 = AddNumbers(1, 2, 3, 4, 5);
Console.WriteLine($"Sum 1: {result1}");
// 2. 배열로 값을 전달
int[] numbersArray = { 10, 20, 30 };
int result2 = AddNumbers(numbersArray);
Console.WriteLine($"Sum 2: {result2}");
}
}
params 쓰면 매개변수 여러 개 한꺼번에 보낼 수 있다.
static void Walk() => Console.WriteLine("Walk");
화살표 연산자를 이용하여 메서드 본문을 줄여 표현할 수 있다.
결괏값이 하나인 단일 표현식일 때는 화살표 기호로 메서드 본문을 줄여 표현할 수 있다.
static int AddAge(int age) => age + 1; // return age + 1의 축약 형식
> static int Add(int a, int b = 1)
{
return a+b;
}
> Add(5)
6
> Add(5,3)
8
기본값 넣어주면 사용할 때 인자 넣어줘도 되고 안 넣어줘도 되고.
이걸로 메서드 오버로드한 효과 낼 수 있다.
Console.WriteLine(Sum(second: 3, first: 2));
순서 상관 없이 매개변수에 값 직접 할당 가능