1. 상수(Constant)

  • 정의: 값을 절대 변경할 수 없는 메모리 공간.
  • 선언 방법:
const 자료형 상수명 = 값;
  • 예시:
const int a = 30; 
const string greeting = "Hello, World!";

2. 열거 형식(Enum)

  • 정의: 종류는 같지만 서로 다른 값을 가지는 상수의 집합.
  • 기반 자료형: 정수 계열만 사용 가능 (byte, sbyte, short, ushort, int, uint, long, ulong, char). 기본값은 int.

a. 선언 방법

enum 열거형식명 : 기반자료형 { 상수1, 상수2 } 
enum 열거형식명 { 상수1 = 값1, 상수2 = 값2 } 
enum 열거형식명 { 상수1 = 값1, 상수2, 상수3 = 값3 }

b. 예시

enum Color { Red = 1, Green = 2, Blue = 3 } 
enum Status : byte { Active = 1, Inactive = 0 }
 

c. 열거형 활용

  • 값 확인:
Console.WriteLine((int)Color.Red); // 출력: 1
  • 열거형 값을 문자열로 출력:
Console.WriteLine(Color.Green); // 출력: Green

3. Nullable 형식

  • 정의: 값이 없을 수 있는 변수 형식.
  • 선언 방법:
데이터형식? 변수이름;

a. 예시

int? a = null; // Nullable 형식 
if (a.HasValue) // 값이 있는지 확인
{
	Console.WriteLine(a.Value); 
} 
else 
{
	Console.WriteLine("No value"); 
}

b. Nullable 속성

  • HasValue: 값이 있는지 확인 (true 또는 false).
  • Value: 변수에 담긴 값 반환.

4. var 형식

  • 정의: 변수에 담긴 데이터에 따라 컴파일러가 자동으로 형식을 지정.
  • 주의사항:
    • 선언과 동시에 값을 초기화해야 함.
    • 지역 변수로만 사용 가능.

예시

var x = 10;        // 컴파일러가 int로 추론
var y = "Hello";   // 컴파일러가 string으로 추론
// var z;           // 오류: 초기화 필요

 


5. 공용 형식 시스템 (CTS)

  • 정의: .NET 프레임워크의 형식 체계 표준.
  • C#의 모든 데이터 형식은 CTS를 기반으로 하며, 다른 .NET 언어들과의 호환성을 보장.
  • 예시:
    • C#의 int는 CTS의 System.Int32에 매핑.
    • C#의 string은 CTS의 System.String에 매핑.

정리

  • 상수: 변경할 수 없는 고정된 값.
  • 열거형: 특정 그룹의 상수를 관리하기 위한 형식.
  • Nullable: 값이 없음을 표현.
  • var: 데이터 형식을 자동 추론.
  • CTS: .NET에서 데이터 형식의 표준을 정의.

1. 데이터 형식 개요

  • 참조 형식: 문자열(string), 오브젝트(object) 형식으로 구분.
  • 값 형식: 숫자 형식, 논리 형식으로 구분.
    • 숫자 형식: 정수 계열, 부동소수점 계열, 소수 계열로 세분화.

2. 정수 계열

정수 데이터를 다루기 위한 형식이며, 크기와 범위가 다릅니다.
효율적인 메모리 사용을 위해 데이터 범위에 맞는 형식을 선택해야 합니다.

데이터 형식설명크기(Byte)범위

byte 부호 없는 정수 1 0 ~ 255
sbyte 부호 있는 정수 1 -128 ~ 127
ushort 부호 없는 정수 2 0 ~ 65,535
short 부호 있는 정수 2 -32,768 ~ 32,767
uint 부호 없는 정수 4 0 ~ 4,294,967,295
int 부호 있는 정수 4 -2,147,483,648 ~ 2,147,483,647
ulong 부호 없는 정수 8 0 ~ 18,446,744,073,709,551,615
long 부호 있는 정수 8 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

양수와 음수 표현: 최상위 비트를 이용하여 0(양수), 1(음수)로 구분.
음수 표현: 2의 보수법

  1. 비트를 반전.
  2. 1을 더함.

예시: -3

  • 00000011 → 비트 반전 → 11111100 → 1 추가 → 11111101

3. 오버플로우와 언더플로우

  • 오버플로우: 데이터가 최대값을 넘으면 0으로 순환.
  • 언더플로우: 데이터가 최소값을 넘으면 최대값으로 순환.
csharp
코드 복사
byte a = 255; a++; // 0

4. 부동소수점 계열

유리수와 실수를 표현하는 데이터 형식.
정수 계열보다 표현 범위가 넓지만 정확도 손실이 있을 수 있음.

데이터 형식설명크기(Byte)범위

float 단일 정밀도 부동소수점 (7자리) 4 ±3.402823e38
double 복수 정밀도 부동소수점 (15~16자리) 8 ±1.79769313486232e308
decimal 29자리 고정소수점 16 매우 정밀한 소수값 표현

 


5. 논리 형식 계열

참과 거짓을 표현.

데이터 형식설명크기(Byte)범위

bool 논리 값 1 true, false

6. 문자와 문자열 형식

  • 문자(char): 단일 문자, 작은 따옴표 사용.
char c = 'A';
  • 문자열(string): 여러 문자의 집합, 큰따옴표 사용.
string s = "Hello";

7. Object 형식

  • 모든 데이터 형식의 조상.
  • 참조 형식이며, 힙(Heap)에 데이터를 저장.

8. 박싱(Boxing)과 언박싱(Unboxing)

  • 박싱: 값 형식 → 참조 형식(object)로 변환.
int a = 20; 
object o = a; // 박싱
  • 언박싱: 참조 형식(object) → 값 형식으로 변환.
object o = 20; 
int a = (int)o; // 언박싱

9. 데이터 크기

  • bit: 0과 1을 표현하는 최소 단위.
  • 니블: 4비트.
  • 바이트(byte): 8비트.
  • 워드(word): CPU의 데이터 처리 단위(16비트 이상).

10. 데이터 구조

  • 필드: 데이터베이스의 열(Column).
  • 레코드: 데이터베이스의 행(Row).
  • 파일: 레코드의 집합.
  • 데이터베이스: 파일의 집합.

1. 변수란 무엇인가?

  • 코드 관점: 값을 대입하거나 변경할 수 있는 요소.
  • 메모리 관점: 데이터를 담는 일정 크기의 공간. 데이터 형식에 따라 크기가 달라집니다.
  • 수학적 관점: 변하는 값을 가진 요소.

컴퓨터에서 변수를 사용하려면 변수 선언이 필요합니다.
변수 선언은 컴파일러에게 필요한 메모리 공간을 예약하도록 지시하는 과정입니다.

int x; // 변수 선언
x = 100; // 데이터 할당
 

2. 메모리와 변수의 관계

변수를 선언하면 메모리 공간이 할당되고, 값을 대입하면 해당 공간에 데이터가 저장됩니다.

예시:

int x = 100;

위 코드는 선언과 동시에 값을 할당한 경우로, 변수 x의 메모리 공간에 100이 저장됩니다.


3. 값 형식(Value Type)과 참조 형식(Reference Type)

변수는 값 형식참조 형식으로 나뉩니다.

a. 값 형식 (Value Type)

  • 데이터를 스택(Stack) 메모리 영역에 저장.
  • 코드 블록이 끝나면 자동으로 제거됩니다.
  • 저장 및 제거 과정: 위 코드에서 b가 먼저 제거되고, 다음으로 a가 제거됩니다.
  • {
        int a = 100;
        int b = 200;
    }

b. 참조 형식 (Reference Type)

  • 데이터는 힙(Heap)에 저장되고, 스택은 힙의 메모리 주소를 참조합니다.
  • 코드 블록이 끝나도 힙에 데이터는 남아 있습니다.
  • 힙의 데이터를 제거하려면 **가비지 컬렉터(Garbage Collector)**가 필요합니다.

예시:

object a = 10;
  • 스택: 변수 a와 메모리 주소값 (&2000) 저장.
  • : 데이터 10이 주소 2000에 저장.

4. 변수의 종류

a. 전역 변수 (Global Variable)

  • 클래스 내부에서 선언되며, 클래스 객체가 살아있는 동안 참조 가능합니다.
  • 기본값이 자동으로 할당됩니다. (예: int 타입은 0)

예시:

class Example
{
    int globalVar; // 기본값 0 자동 할당
}

b. 지역 변수 (Local Variable)

  • 메서드 내에서 선언되며, 메서드 호출이 끝나면 메모리에서 제거됩니다.
  • 기본값이 자동으로 할당되지 않으므로, 초기화를 해야 사용 가능합니다.

예시:

public void Method()
{
    int localVar;
    localVar = 100; // 초기화 필수
}

5. 메모리 구조 요약

  • 스택(Stack): 값 형식 데이터를 저장하며, 데이터가 코드 블록이 끝나면 제거됩니다.
  • 힙(Heap): 참조 형식 데이터를 저장하며, 데이터가 명시적으로 제거되지 않으면 계속 유지됩니다.

1. Connection Pooling이란?

  • Connection Pooling은 데이터베이스 연결을 효율적으로 관리하기 위한 방법입니다.
  • DB 연결은 클라이언트와 서버 간의 핸드셰이크, 로그인 등으로 시간이 소요되므로, 기존의 연결을 유지하고 재활용하여 성능을 향상시킵니다.
  • ADO.NET에서는 Connection Pooling이 기본적으로 활성화(ON) 되어 있으며, 이를 통해 연결 작업의 비용을 줄입니다.

2. Connection Pooling의 동작 원리

  1. 연결 생성:
    • 클라이언트가 SqlConnection 객체를 생성하고 Open()을 호출하면, 새로운 연결이 생성되고 Connection Pool에 추가됩니다.
    • SQL 서버에는 이를 나타내는 SPID(Session Process ID)가 생성됩니다.
  2. 연결 재활용:
    • 연결이 닫혀도(Connection Close) Pool에 반환되어 대기 상태로 유지됩니다.
    • 새로운 연결 요청이 발생하면 Pool에서 기존 연결을 재사용합니다.
  3. Pool 크기 관리:
    • 최소 연결 수(Min Pool Size): Pool에 유지될 최소 연결 수.
    • 최대 연결 수(Max Pool Size): Pool에 저장될 최대 연결 수. 기본값은 100입니다.
    • 필요 시 Pool 크기를 동적으로 조정하여 리소스를 관리합니다.
  4. Timeout 관리:
    • 연결 요청이 Queue에서 대기할 수 있는 최대 시간(Connection Timeout). 기본값은 15초입니다.
    • Timeout 안에 연결을 확보하지 못하면 예외가 발생합니다.

3. Connection Pool 생성 기준

  • Connection String:
    • 동일한 Connection String을 사용하는 경우 같은 Pool을 공유합니다.
    • Connection String이 조금이라도 다르거나, 옵션 순서가 다르면 별도의 Pool이 생성됩니다.
  • 인증 방식:
    • Windows Authentication: 사용자 계정별로 별도의 Pool이 생성됩니다.
    • SQL Authentication: 공통 Pool을 사용하여 성능이 더 좋습니다.
  • 프로세스와 AppDomain:
    • 프로세스와 AppDomain이 다르면 별도의 Pool이 생성됩니다.

4. Connection Pool 옵션

Connection String에서 설정 가능한 주요 옵션:

옵션설명기본값

Pooling Connection Pooling 활성화 여부. true로 설정 시 활성화. true
Min Pool Size Pool에서 유지할 최소 연결 수. 1
Max Pool Size Pool에서 유지할 최대 연결 수. 100
Connection Timeout 연결 요청 대기 시간. 초 단위로 설정. 15
Enlist 현재 트랜잭션 컨텍스트에 연결을 자동 등록할지 여부. true

예제 Connection String

string connectionString = "Data Source=MyServer;Initial Catalog=MyDB;Integrated Security=true;" +
                          "Min Pool Size=20;Max Pool Size=100;Connection Timeout=15;Pooling=true;";

5. Connection Pool 관리

  • Pool 초기화:
    • SqlConnection.ClearAllPools()를 호출하면 모든 Connection Pool이 초기화되고 연결이 닫힙니다.
    • 사용하지 않는 연결은 자동으로 제거되어 SQL 서버 부하를 줄입니다.

사용 예제

using (SqlConnection conn = new SqlConnection(connectionString))
{
    conn.Open();
    // 데이터베이스 작업 수행
    conn.Close(); // 연결은 Pool로 반환
}
SqlConnection.ClearAllPools(); // Pool 초기화

6. Connection Pool 성능 관리

  • 적절한 Pool 크기 설정:
    • 최소 Pool 크기(Min Pool Size)를 설정하면 서버가 항상 준비된 연결을 유지하므로 대기 시간이 줄어듭니다.
    • 최대 Pool 크기(Max Pool Size)를 통해 과도한 리소스 사용을 제한합니다.
  • Connection String 최적화:
    • 통일된 Connection String을 사용하여 불필요한 Pool 생성을 방지합니다.
  • Idle Timeout:
    • 사용하지 않는 연결은 일정 시간 후 제거됩니다. 이 시간을 관리하여 리소스를 최적화할 수 있습니다.

7. Connection Pool 모니터링

  • SQL Server SPID 확인:
    • SQL Server에서 sys.dm_exec_sessions 및 sys.dm_exec_requests를 사용하여 Pool에 연결된 세션(SPID)을 확인할 수 있습니다.
    SELECT * FROM sys.dm_exec_sessions WHERE is_user_process = 1;
  • ADO.NET 성능 카운터:
    • .NET 성능 카운터를 통해 Pool 상태를 모니터링할 수 있습니다.
    • 사용 가능한 연결 수:
       
      .NET Data Provider for SqlServer -> NumberOfPooledConnections

1. 증감 연산자

  • 전위 증가 연산자 (++a):
    변수를 증가시킨 후 해당 구문을 실행.
  • 후위 증가 연산자 (a++):
    해당 구문을 실행한 후 변수를 증가.

예시:

int a = 10; 
Console.WriteLine(a++); // 출력: 10 (증가는 이후에 실행) 
Console.WriteLine(++a); // 출력: 12 (증가는 먼저 실행)

2. 관계 연산자

  • 논리형식(bool) 결과 반환 (true 또는 false).연산자설명 
    == 두 피연산자가 같으면 true.
    != 두 피연산자가 다르면 true.

예시:

int x = 5, y = 10; 
Console.WriteLine(x == y); // 출력: False 
Console.WriteLine(x != y); // 출력: True

3. 논리 연산자

  • AND (&&): 두 조건이 모두 참일 때 true.
  • OR (||): 하나라도 참이면 true.
  • NOT (!): 논리값을 반전.

예시:

bool a = true, b = false; 
Console.WriteLine(a && b); // 출력: False 
Console.WriteLine(a || b); // 출력: True 
Console.WriteLine(!a); // 출력: False

4. 조건 연산자 (?:)

  • 형식: 조건식 ? 참일 때 값 : 거짓일 때 값.
  • 조건식의 결과는 논리값(true 또는 false).

예시:

int a = 30; 
string result = a == 30 ? "삼십" : "삼십 아님"; 
Console.WriteLine(result); // 출력: 삼십

5. Null 조건부 연산자 (?.)

  • 형식: 객체?.멤버 또는 객체?[인덱스].
  • 객체가 null이면 null 반환, 아니면 멤버에 접근.

예시:

class Foo 
{ 
	public int Member { get; set; } 
} 
Foo foo = null; 
int? bar = foo?.Member; // foo가 null이므로 bar는 null

6. Null 병합 연산자 (??)

  • 형식: op1 ?? op2.
  • op1이 null이면 op2 반환, 그렇지 않으면 op1 반환.

예시:

string message = null; 
string result = message ?? "Default message"; 
Console.WriteLine(result); // 출력: Default message​

7. 비트 연산자

  • 왼쪽 시프트 (<<): 비트를 왼쪽으로 이동.
  • 오른쪽 시프트 (>>): 비트를 오른쪽으로 이동.
  • XOR (^): 두 비트가 다를 때 1.
  • NOT (~): 모든 비트를 반전.

시프트 연산 예시:

int a = 240, b = 2; 
Console.WriteLine(a << b); // 출력: 960 (240 * 2^2) 
Console.WriteLine(a >> b); // 출력: 60 (240 / 2^2)​

정리

  • 증감 연산자: 전위와 후위의 차이를 이해.
  • 관계 및 논리 연산자: 분기와 조건 설정에 필수.
  • 조건 연산자: 간단한 조건문 처리에 유용.
  • Null 조건부 연산자: 객체가 null인지 확인 후 멤버 접근.
  • Null 병합 연산자: null 기본값을 처리하는 데 활용.
  • 비트 연산자: 낮은 수준의 데이터 조작에 필수.
 

1. 데이터 형식 변환이란?

  • 정의: 변수를 다른 데이터 형식의 변수로 옮겨 담는 것을 변환이라고 합니다.
  • 변환에는 두 가지 방식이 있습니다:
    1. 암시적 변환: 데이터 손실이 없는 경우 자동으로 수행.
    2. 명시적 변환: 데이터 손실 가능성이 있는 경우 개발자가 명시적으로 수행.

2. 정수 데이터 형식 변환

a. 작은 정수 → 큰 정수
  • 변환 시 문제가 발생하지 않습니다.
  • 예: byte → int
b. 큰 정수 → 작은 정수
  • 데이터가 범위를 초과하면 오버플로우 발생.
  • 예: int → byte 
int a = 256;
byte b = (byte)a; // b = 0 (오버플로우 발생)

c. 부호 있는 정수 → 부호 없는 정수

  • 음수 값을 변환하면 언더플로우가 발생.
  • 예: int → uint
int a = -1;
uint b = (uint)a; // b = 4294967295 (언더플로우)

3. 부동소수점 데이터 형식 변환

a. 부동소수점 → 정수

  • 소수점 이하를 버리고 정수 값만 남습니다. 반올림은 하지 않습니다.
  • 예:
     
double d = 3.9; 
int i = (int)d; // i = 3

b. float ↔ double 변환

  • 부동소수점은 소수를 이진수로 저장하므로 정밀도 손실이 있을 수 있습니다.
  • 예:
float f = 1.123456789f; // 제한된 정밀도 (7자리)
double d = f; // 정밀도가 손상될 수 있음

4. 문자와 숫자 변환

a. 문자 → 숫자

  • Parse() 또는 Convert.ToInt32() 메소드를 사용.
  • 예:
string s = "123"; 
int i = int.Parse(s); // i = 123

b. 숫자 → 문자

  • ToString() 메소드를 사용.
  • 예:
int i = 123; 
string s = i.ToString(); // s = "123"

 


5. 변환의 주의점

  • 정수 변환: 범위 초과 여부 확인 (오버플로우/언더플로우).
  • 부동소수점 변환: 정밀도 손실 가능성 이해.
  • 문자와 숫자 변환: 잘못된 입력 처리 대비 (예외 처리).

1. 테이블 생성 구문 형식

CREATE TABLE 테이블_이름 (
    컬럼명1 DATATYPE [DEFAULT 값],
    컬럼명2 DATATYPE [DEFAULT 값],
    컬럼명3 DATATYPE [DEFAULT 값]
);

테이블 생성 규칙

  • 테이블 이름: 적절한 이름을 사용하고 단수형 권장.
  • 컬럼 이름: 중복 불가, 데이터베이스 내에서 일관성 유지.
  • 데이터 유형 지정: 모든 컬럼에 반드시 데이터 유형 지정.
  • 명명 규칙:
    • 문자(A-Z, a-z), 숫자(0-9), _, $, #만 허용.
    • 예약어 사용 금지.
  • SQL 문법: 대소문자 구분하지 않음, 문장 끝에 ; 사용.

2. CREATE TABLE 예제

CREATE TABLE PLAYER (
    PLAYER_ID CHAR(7) NOT NULL,
    PLAYER_NAME VARCHAR2(20) NOT NULL,
    TEAM_ID CHAR(3) NOT NULL,
    E_PLAYER_NAME VARCHAR2(40),
    NICKNAME VARCHAR2(30),
    JOIN_YYYY CHAR(4),
    POSITION VARCHAR2(10),
    BACK_NO NUMBER(2),
    NATION VARCHAR2(20),
    BIRTH_DATE DATE,
    SOLAR CHAR(1),
    HEIGHT NUMBER(3),
    WEIGHT NUMBER(3),

    CONSTRAINT PLAYER_PK PRIMARY KEY (PLAYER_ID),
    CONSTRAINT PLAYER_FK FOREIGN KEY (TEAM_ID) REFERENCES TEAM(TEAM_ID)
);

설명

  • DATE 유형: 별도 크기 지정하지 않음.
  • 제약 조건:
    • NOT NULL: 필수 입력.
    • PRIMARY KEY: 고유 식별 키.
    • FOREIGN KEY: 다른 테이블의 키를 참조.
  • 제약 조건 정의 위치:
    • 컬럼 레벨: 각 컬럼의 정의에 직접 추가.
    • 테이블 레벨: 테이블 생성 마지막에 선언.

3. 제약조건 (CONSTRAINT)

제약조건 설명

구분설명

PRIMARY KEY - 기본키: 행 데이터를 고유하게 식별.
- NULL 입력 불가.
- 자동으로 UNIQUE 인덱스 생성.
UNIQUE KEY - 고유키: 행 데이터를 고유하게 식별.
- NULL 값 허용.
NOT NULL - NULL 값 입력 금지.
- 필수 입력 컬럼.
CHECK - 값의 범위 제한.
- 논리식 평가(TRUE or FALSE).
FOREIGN KEY - 다른 테이블과의 관계를 정의.
- 참조 무결성 제약 옵션 제공.

4. 생성된 테이블 구조 확인 (DESC)

Oracle:

DESC PLAYER;

MySQL:

DESCRIBE PLAYER;

5. SELECT 문을 통한 테이블 생성

SELECT를 사용한 테이블 복제

CREATE TABLE TEMPPLAYER
    AS SELECT * FROM PLAYER;

특징

  • 기존 테이블에서 컬럼과 데이터를 복제.
  • 제약 조건:
    • NOT NULL: 유지.
    • PRIMARY KEY, FOREIGN KEY, CHECK: 적용되지 않음.
  • 제약 조건 추가:
     
ALTER TABLE TEMPPLAYER
ADD CONSTRAINT TEMPPLAYER_PK PRIMARY KEY (PLAYER_ID);

6. 실습 예제

테이블 생성

CREATE TABLE TEAM (
    TEAM_ID CHAR(3) PRIMARY KEY,
    TEAM_NAME VARCHAR2(30) NOT NULL
);

CREATE TABLE PLAYER (
    PLAYER_ID CHAR(7) NOT NULL,
    PLAYER_NAME VARCHAR2(20) NOT NULL,
    TEAM_ID CHAR(3) NOT NULL,
    POSITION VARCHAR2(10),
    BIRTH_DATE DATE,

    CONSTRAINT PLAYER_PK PRIMARY KEY (PLAYER_ID),
    CONSTRAINT PLAYER_FK FOREIGN KEY (TEAM_ID) REFERENCES TEAM(TEAM_ID)
);

테이블 구조 확인

DESC PLAYER;

데이터 삽입

INSERT INTO TEAM (TEAM_ID, TEAM_NAME) VALUES ('001', 'Team A');
INSERT INTO PLAYER (PLAYER_ID, PLAYER_NAME, TEAM_ID, POSITION, BIRTH_DATE)
VALUES ('P001', 'John Doe', '001', 'Forward', TO_DATE('1990-01-01', 'YYYY-MM-DD'));

데이터 조회

SELECT * FROM PLAYER;

1. 메소드란?

  • 정의: 특정 작업을 수행하는 일련의 코드를 하나의 이름으로 묶은 것.
  • 다양한 언어에서의 표현:
    • C++: 함수 (Function)
    • 파스칼: 프로시저 (Procedure)
    • 비주얼 베이직: 서브 루틴 (Subroutine)

2. 메소드 선언 형식

한정자 반환형식 메소드이름(매개변수)
  • 한정자: 메소드의 속성 정의 (예: public, static).
  • 반환형식: 메소드가 반환하는 데이터의 형식.
  • 메소드 이름: 호출 시 사용할 이름.
  • 매개변수: 메소드 실행에 필요한 입력값.

예시:

public int Add(int a, int b)
{
    return a + b;
}

3. return 키워드

  • 프로그램의 흐름을 호출자로 되돌립니다.
  • 반환형식이 존재할 경우 반환값과 반환형식이 일치해야 합니다.

예시 (재귀 호출):

public int Fibonacci(int n)
{
    if (n < 2)
        return n;
    return Fibonacci(n - 1) + Fibonacci(n - 2);
}

4. 매개변수 전달 방식

a. 값에 의한 전달

  • 매개변수로 데이터를 복사하여 전달.
public void Swap(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
}

int x = 3, y = 4;
Swap(x, y);
Console.WriteLine($"{x}, {y}"); // 결과: 3, 4 (값이 변경되지 않음)

b. 참조에 의한 전달 (ref)

  • 매개변수를 참조하여 원본 데이터를 변경.
public void Swap(ref int a, ref int b)
{
    int temp = a;
    a = b;
    b = temp;
}

int x = 3, y = 4;
Swap(ref x, ref y);
Console.WriteLine($"{x}, {y}"); // 결과: 4, 3

c. 출력 전용 매개변수 (out)

  • 메소드에서 결과를 출력하는 용도로 사용.
public void Divide(int a, int b, out int quotient, out int remainder)
{
    quotient = a / b;
    remainder = a % b;
}

int quotient, remainder;
Divide(10, 3, out quotient, out remainder);
Console.WriteLine($"Quotient: {quotient}, Remainder: {remainder}");

5. 메소드 오버로딩

  • 같은 이름의 메소드를 매개변수의 타입, 개수로 구분하여 여러 개 정의.
public int Add(int a, int b)
{
    return a + b;
}

public double Add(double a, double b)
{
    return a + b;
}​

6. 가변 길이 매개변수 (params)

  • 개수가 유동적인 매개변수를 받을 때 사용.
public int Sum(params int[] numbers)
{
    int sum = 0;
    foreach (int num in numbers)
        sum += num;
    return sum;
}

int result = Sum(1, 2, 3, 4);
Console.WriteLine(result); // 출력: 10

7. 명명된 매개변수

  • 매개변수 이름을 명시적으로 지정하여 호출.
public void PrintInfo(string name, int age)
{
    Console.WriteLine($"Name: {name}, Age: {age}");
}

PrintInfo(age: 30, name: "Alice");

8. 선택적 매개변수

  • 기본값을 제공하여 필요에 따라 값을 전달하지 않을 수 있음.
public void PrintMessage(string message = "Hello, World!")
{
    Console.WriteLine(message);
}

PrintMessage(); // 출력: Hello, World!
PrintMessage("Hi!"); // 출력: Hi!

9. 로컬 함수

  • 메소드 내부에 정의된 함수로, 해당 메소드에서만 사용 가능.
public void Calculate()
{
    int counter = 0;

    void LocalFunction(int a, int b)
    {
        counter++;
        Console.WriteLine($"{a} + {b} = {a + b}, Counter: {counter}");
    }

    LocalFunction(1, 2);
    LocalFunction(3, 4);
}

정리

  • 메소드는 코드를 재사용하고 모듈화하기 위한 핵심 도구.
  • 다양한 매개변수 전달 방식 (ref, out, params)과 유연한 호출 방식을 제공.
  • 로컬 함수와 메소드 오버로딩으로 코드의 가독성과 효율성을 높일 수 있음.

1. 객체 지향 프로그래밍 (OOP)

  • 정의: 코드 내의 모든 것을 객체로 표현하는 프로그래밍 패러다임.
  • 객체(Object): 세상의 모든 것을 지칭하며, 속성과 기능으로 이루어집니다.
    • 속성: 데이터를 통해 표현 (예: 다리, 귀).
    • 기능: 메소드를 통해 표현 (예: 뛰기, 듣기).

2. 클래스(Class)

  • 정의: 객체를 생성하기 위한 청사진(모형).
  • 예시:
class Cat
{
    public string Color; // 데이터: 속성
    public void Meow()   // 메소드: 기능
    {
        Console.WriteLine($"{Color} 고양이: 야옹");
    }
}

Cat kitty = new Cat();  // Cat 클래스의 객체 생성

3. 클래스와 객체의 관계

  • 클래스는 복합 데이터 형식의 참조 형식입니다.
  • **객체(Object)**는 클래스의 인스턴스(실체)입니다.
    Cat kitty = new Cat();
    • new: 생성자를 호출해 객체를 힙(Heap)에 생성.
    • kitty: 생성된 객체의 참조를 저장.

4. 생성자(Constructor)와 종료자(Destructor)

a. 생성자

  • 클래스와 같은 이름을 가지며 객체 생성 시 호출됩니다.
  • 객체를 초기화하기 위한 용도로 사용됩니다.
  • 예시:
class Cat
{
    public string Color;

    // 생성자
    public Cat(string color)
    {
        Color = color;
    }

    public void Meow()
    {
        Console.WriteLine($"{Color} 고양이: 야옹");
    }
}

Cat kitty = new Cat("검은색"); // 생성자 호출

b. 종료자

  • 객체가 소멸될 때 호출되는 특별한 메소드.
  • 매개변수나 한정자가 없으며 오버로딩 불가능.
  • CLR의 가비지 컬렉터가 객체의 소멸 시점을 판단해 호출.
  • 예시:
class Cat
{
    ~Cat()
    {
        Console.WriteLine("Cat 객체가 소멸되었습니다.");
    }
}

5. 정적 필드와 메소드 (Static)

  • static 한정자를 사용해 클래스 자체에 소속되는 필드와 메소드.
  • 특징:
    • 클래스의 모든 인스턴스가 공유.
    • 객체를 생성하지 않고 호출 가능.
  • 예시:
class Counter
{
    public static int Count = 0;

    public static void Increment()
    {
        Count++;
    }
}

Counter.Increment(); // 객체 없이 호출
Console.WriteLine(Counter.Count); // 출력: 1

6. 클래스의 기본 구조

class ClassName
{
    // 필드 (Field): 데이터 저장
    public string FieldName;

    // 생성자 (Constructor): 객체 초기화
    public ClassName(string value)
    {
        FieldName = value;
    }

    // 메소드 (Method): 동작 정의
    public void MethodName()
    {
        Console.WriteLine($"Field: {FieldName}");
    }

    // 정적 메소드 (Static Method)
    public static void StaticMethod()
    {
        Console.WriteLine("This is a static method.");
    }
}

정리

  • 클래스는 객체를 생성하기 위한 청사진으로, 속성(필드)과 기능(메소드)을 포함.
  • 객체는 클래스의 인스턴스로, new 키워드를 통해 생성.
  • 생성자는 객체를 초기화하고, 종료자는 객체 소멸 시 호출.
  • 정적 필드/메소드는 클래스 자체에 속하며, 모든 인스턴스가 공유 가능.

1. 객체와 다형성

  • 다형성(Polymorphism): 객체가 여러 형태를 가질 수 있는 성질.
    • 하위 형식 다형성: 파생 클래스가 기반 클래스의 메소드를 재정의하여 다양한 동작을 실행.

a. 예제: 다형성

class ArmorSuite
{
    public virtual void Initialize()
    {
        Console.WriteLine("ArmorSuite: 초기화");
    }
}

class IronMan : ArmorSuite
{
    public override void Initialize()
    {
        base.Initialize(); // 기반 클래스 메소드 호출
        Console.WriteLine("IronMan: 초기화");
    }
}

2. 메소드 오버라이딩

  • 조건:
    • 메소드는 virtual 키워드로 선언되어야 함.
    • override 키워드로 재정의.
    • private 메소드는 오버라이딩 불가.

a. 예제

class BaseClass
{
    public virtual void MyMethod()
    {
        Console.WriteLine("BaseClass: MyMethod");
    }
}

class DerivedClass : BaseClass
{
    public override void MyMethod()
    {
        Console.WriteLine("DerivedClass: MyMethod");
    }
}

b. 메소드 감추기 (new 키워드)

  • 기반 클래스의 메소드를 감추고 파생 클래스 메소드만 표시.
class BaseClass
{
    public void MyMethod()
    {
        Console.WriteLine("BaseClass: MyMethod");
    }
}

class DerivedClass : BaseClass
{
    public new void MyMethod()
    {
        Console.WriteLine("DerivedClass: MyMethod");
    }
}

c. 메소드 봉인 (sealed 키워드)

  • 오버라이딩된 메소드의 추가 재정의를 금지.
class BaseClass
{
    public virtual void MyMethod()
    {
        Console.WriteLine("BaseClass: MyMethod");
    }
}

class DerivedClass : BaseClass
{
    public sealed override void MyMethod()
    {
        Console.WriteLine("DerivedClass: MyMethod");
    }
}

3. 중첩 클래스

  • 클래스 안에 선언된 클래스.
  • 외부 클래스의 모든 멤버(심지어 private)에 접근 가능.

예제

class OuterClass
{
    private int number = 42;

    class NestedClass
    {
        public void DisplayNumber(OuterClass outer)
        {
            Console.WriteLine($"Number: {outer.number}");
        }
    }
}

4. 분할 클래스

  • partial 키워드를 사용하여 여러 파일에 걸쳐 하나의 클래스를 정의.
  • 코드 관리 및 분할 작업에 유용.

예제

partial class MyClass
{
    public void Method1()
    {
        Console.WriteLine("Method1");
    }
}

partial class MyClass
{
    public void Method2()
    {
        Console.WriteLine("Method2");
    }
}

5. 확장 메소드

  • 기존 클래스의 기능을 확장하는 메소드.
  • 정적 클래스와 this 키워드를 활용.

예제

public static class StringExtensions
{
    public static string ToUpperFirst(this string input)
    {
        if (string.IsNullOrEmpty(input)) return input;
        return char.ToUpper(input[0]) + input.Substring(1);
    }
}

// 사용
string name = "john";
Console.WriteLine(name.ToUpperFirst()); // 출력: John

6. 클래스 vs 구조체

특징클래스구조체

키워드 class struct
형식 참조 형식 값 형식
복사 방식 얕은 복사 깊은 복사
생성 방법 new 키워드 필요 선언만으로 생성 가능
생성자 매개변수 없는 생성자 가능 불가능
상속 가능 불가능

예제

struct Point
{
    public int X;
    public int Y;

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

Point p1 = new Point(10, 20);
Console.WriteLine($"X: {p1.X}, Y: {p1.Y}");

7. 튜플 (Tuple)

  • 여러 필드를 담을 수 있는 구조체.
  • 임시적으로 복합 데이터를 다룰 때 사용.

a. 명명되지 않은 튜플

var tuple = (123, 789);
Console.WriteLine(tuple.Item1); // 출력: 123
Console.WriteLine(tuple.Item2); // 출력: 789

b. 명명된 튜플

var person = (Name: "John", Age: 30);
Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");

정리

  • 객체는 클래스의 인스턴스이며, 다형성, 오버라이딩, 중첩 클래스, 확장 메소드 등을 통해 강력한 유연성을 제공합니다.
  • 구조체는 값 형식으로 메모리 관리 및 간단한 데이터 저장에 유용.
  • 튜플은 임시적인 복합 데이터를 간단히 표현.

+ Recent posts