C#

C#

Tags
C#
Published
Author

런타임

운영체제 위 또는 운영체제 자체에서 실행되면서 특정 프로그래밍 언어가 구동될 수 있는 환경

컴파일

사람이 이해하는 언어를 컴퓨터가 이해할 수 있는 언어로 바꾸는 과정

Namespace

성격이나 하는 일에 따라 클래스, 메소드 등을 하나의 이름으로 묶어 두는 것

MVP 패턴(Model-View-Presenter)

  • Model
    • 프로그램에서 사용되는 실제 데이터 및 데이터 조작 로직을 처리하는 부분
  • View
    • 사용자에게 제공되어 보여지는 UI 부분
  • Presenter
    • View에서 요청한 정보를 Model로부터 가공해서 View로 전달하는 부분

전체적인 흐름

  1. View로 사용자의 입력이 들어옴
  1. View는 Presenter에 작업을 요청
  1. Presenter에서 필요한 데이터를 Model에 요청
  1. Model은 Presenter에 필요한 데이터를 응답
  1. Presenter는 View에 데이터를 응답
  1. View는 Presenter로부터 받은 데이터로 화면에 보여주게 됨

Static

  • 변수나 메소드에 키워드로 사용
  • 클래스가 메모리에 올라갈 때 자동으로 생성이 된다.
    • static 변수는 객체를 선언만 해도 메모리가 할당되며 일반적인 변수들이 객체가 새로 생성될 때
  • 인스턴스(객체) 생성 없이 바로 사용 가능
  • 정적메서드는 인스턴스 메서드와 달리 클래스로부터 객체를 생성하지 않고 직접 [클래스명.메서드명]형식으로 호출하는 메서드

사용하는 이유

  • 자주 변하지 않는 일정한 값 혹은 설정 정보 같은 공용 자원에 대한 접근에 있어서 매번 메모리에 로딩 혹은 값을 읽어 들이는 것보다 일종의 ‘전역 변수’와 같은 개념을 통해서 접근하는 것이다.
  • 클래스의 일반 멤버 변수는 클래스의 객체가 생성될 때, 각 객체마다 따로 생기지만, 정적 변수는 해당 클래스가 처음으로 사용되는 때에 한번만 초기화되어 계속 동일한 메모리를 사용하게 된다.

Dynamic

컴파일러에게 변수의 타입을 체크하지 않도록하고 런타임시까지 해당 타입을 알 수 없음을 표시한다.
  • 내부적으로 dynamic 타입은 object 타입을 사용하므로 dynamic 타입의 변수는 중간에 다른 타입의 값을 가질 수 있다.
  • 캐스팅(현재 보유하고 있는 참조 유형과 다른 유형의 개체에 대한 참조를 생성하는 것을 의미)가 필요없다

DynamicObject 클래스

DLR(Dynamic Runtime Language) : 동적언어 런타임 네임스페이스인 System.Dynamic에는 두개의 중요한 클래스
  1. ExpandoObject Class
      • 개발자가 dynamic 타입을 쉽게 생성하도록 도와주는 클래스
      • dynamic 타입에 속성, 메서드, 이벤트를 동적으로 쉽게 할당할 수 있게 도와주는 클래스
      • 클래스를 사용하면 객체에 동적으로 속성을 추가하거나 속성을 제거
  1. DynamicObject Class
      • 보다 유연한 Customization을 위한 고급 dynamic 기능을 지원하는 클래스
      • DynamicObject를 상속 받고, 3개의 methods를 override해야함(TryGetMember, TrySetMember, TryInvokeMember)
      • 인덱서, 메서드. 생성자. 단항연산자, 이항 연산자 등의 동적 호출을 처리하는 비슷한 메서들을 갖고 있어 멤버들 중 원하는 것을 재정의하여 자신만의 동적 멤버를 만들수 있다.

클래스

새로운 데이터 타입을 만드는 데이터 타입 생성기
구조체는 값 타입이고 클래스는 참조 타입이다.
변수를 선언하면 참조변수에 해당하는 메모리 생성된다.
Person sister; // 참조 변수 선언(참조변수에 해당하는 메모리만 생성) // 실제 메모리는 new 연산자를 이용해서 생성해주어야한다. sister new Person(); // 실제 메모리 생성 => Person sister = new Person(); // 동시에 객체 변수선언 및 메모리 생성

구성요소

  • 생성자 : 클래스안에 구성된 메서드의 특수한 형태
  • 필드
  • 속성(프로퍼티)
  • 메서드
  • 이벤트
  • 소멸자
private: 클래스 내부에서만 사용하기 위해서, 멤버들에 대한 접근을 해당 클래스 내에서만 가능하도록하는 접근자
public: 어느 클래스, 객체에서건 접근이 가능하도록 할 대 사용하는 접근 변경자
protected : 정의된 클래스 내에서와 파생클래스 인스턴스에서 접근이 가능하다.
파생클래스 : 정의된 클래스로부터 상속받은 클래스
internal : 정의된 프로젝트 안에서만 접근 가능
protected internal : 현재의 프로젝트 안에서 클래스 내부 도는 상속받은 클래스에서 접근이 가능하고 객체로 접근이 가능
class Person : Form // Form 클래스로부터 상속( : ) 받았음을 의미
C#에서는 new를 사용해서 메모리를 생성했지만 별도로 메모리를 제거하지 않아도 된다. 그 이유는 가비지 콜렉터가 있어 알아서 메모리를 제거해준다.
한 class를 여러 파일에 나눠서 선언할 때에는 반드시 partial키워드를 사용해야 한다.

접근 지정자

접근지정자
의미
public
어디서든지 접근 가능
abstract
현재의 프로젝트 안에서만 접근 가능 인스턴스화 할 수 없으며 상속받은 경우에만 가능
internal abstract
현재의 프로젝트 안에서만 접근 가능 인스턴스화 할 수 없으며 상속받은 경우에만 가능
public abstract
어디서든지 접근 가능 인스턴스화 할 수 없으며 상속받은 경우에만 가능
sealed
현재의 프로젝트에서만 접근 가능 상속될수 없으며 인스턴스화 할 수 있음
internal sealed
현재의 프로젝트에서만 접근 가능 상속될수 없으며 인스턴스화 할 수 있음
public sealed
어디서든지 접근 가능 상속될수 없으며 인스턴스화 할 수 있음
internal
현재의 프로젝트 안에서만 접근 가능

InitializeComponent();

디자이너단에 정의된 Form컴포넌트 정의를 호출하는 메서드이다.

메서드

개체 또는 클래스에서 수행할 수 있는 계산이나 작업을 구현하는 멤버
  • 정적 메서드
    • static 한정자를 사용하여 선언된 메서드
    • 정적 멤버에 직접적으로만 엑세스 가능
  • 인스턴스 메서드
    • static 한정자를 사용하지 않고 선언된 메서드
    • 정적 및 인스턴스 멤버 둘 다에 액세스 가능
    • 호출된 인스턴스는 this로 명시적으로 액세스 가능
  • 가상 메서드
    • 파생 클래스가 좀 더 구체적인 구현의 동작을 수정하는 파생 클래스에서 구현된 메서드
    • 파생된 클래스에서 재정의될 수 있음
  • 재정의 메서드
    • 기본 클래스 구현의 동작을 수정하는 파생 클래스에서 구현된 메서드
  • 추상 메서드
    • 모든 파생 클래스에서 반드시 재정의해야 하는 기본 클래스에서 선언된 메서드
    • 구현이 없는 가상 메서드
    • abstract 한정자를 사용하여 선언되며 추상 클래스에서만 허용

매개변수

메서드에 값 또는 변수 참조를 전달하는 데 사용
  • 값 매개변수
    • 입력 매개 변수를 전달하는데 사용
    • 매개 변수에 전달된 인수에서 초기 값을 가져오는 지역 변수
  • 참조 매개변수
    • 인수를 참조로 전달하는데 사용
    • 인수는 한정된 값을 가진 변수여야 함
    • ref
  • 출력 매개변수
    • 인수를 참조로 전달하는데 사용
    • 인수에 값을 명시적으로 할당할 필요가 없음
    • out
  • 매개 변수 배열
    • 다양한 개수와 인수가 메서드에 전달되도록 허용
    • params
    • 1차원 배열 형식이어야 함

생성자

반환 형식이 없고 포함하는 클래스와 동일한 이름을 갖는 메서드처럼 선언됨
  • 인스턴스 생성자
    • 클래스의 인스턴스를 초기화하는데 필요한 작업을 구현하는 멤버
  • 정적 생성자
    • 처음 로드될 때 클래스 자체를 초기화하는데 필요한 동작을 구현하는 멤버
    • static 한정자 포함

속성

  • get 접근자 : 값을 읽음, 반환 값을 갖는 매개 변수 없는 매서드
  • set 접근자 : 값을 씀, value라는 단일 매개 변수를 가지며 반환 형식이 없는 메서드

인덱서

개체가 배열과 같은 방식으로 인덱싱될 수 있도록 하는 멤버
  • this[] 사이에 작성된 매개 변수 목록을 합쳐서 구성원 이름으로 사용한다는 점을 제외하고 속성처럼 선언

이벤트

클래스 또는 개체가 알림을 제공할 수 있도록 하는 멤버
  • 이벤트는 선언에 event 키워드가 포함되고 형식이 대리자 형식이어야 한다는 점을 제외하고 필드처럼 선언

Instance(인스턴스)

같은 클래스에 속하는 개개의 객체로, 하나의 클래스에서 생성된 객체를 말한다.
이때 추상적인 개념인 클래스에서 실제 객체를 생성하는 것을 인스턴스화(instantiation)라고 한다.
클래스명 참조 변수명; : 클래스타입 변수 선언(주소값을 저장할 참조 변수 선언)
참조변수명 = new 클래스명(); : 해당 클래스의 인스턴스를 생성한 뒤, 인스턴스 주소값을 변수에 저장
클래스명 객체명 = new 클래스명();

Interface

클래스내의 구성요소들의 구현부가 없고 선언부의 집합으로만 이루어진 클래스
  • 인터페이스 멤버는 default로 전부 public
  • 인터페이스를 이용해서 객체 생성이 되지 않는다.
  • 내부에 필드를 가질 수 없다.
  • 어떠한 접근자, 한정자를 붙일 수 없다.

Overriding(오버라이딩)

클래스간 상속 관계에서 메서드를 재정의하는 방법

기본 형태

class Animal { public void sleep() { Console.WriteLine("동물이 자다"); } } class Monkey: Animal { public void sleep() { Console.WriteLine("원숭이가 자다"); } } Monkey monkey = new Monkey(); monkey.sleep(); // output : 원숭이가 자다
부모 클래스의 메소드를 자식(파생)클래스의 메소드가 덮어 쓴 상황 ⇒ 오버라이딩
메서드를 오버라이딩 할 때 부모 클래스에서는 virtual로, 자식 클래스는 override 키워드로 메서드들을 정의해야한다.
  1. 부모 클래스에 virtual, 자식 클래스에 override 키워들 사용하는 경우
    1. class Money: Animal { public new void sleep() { Console.WriteLine("원숭이가 자다"); } }
  1. 부모 클래스에 virtual를 미정의 시, 자식 클래스에서 메소드 앞에 new를 붙이면 된다.
    1. class Money: Animal { public new void sleep() { Console.WriteLine("원숭이가 자다"); } }

base

오버라이딩을 해도 부모 클래스의 메소드를 사용할 수 있는 방법
class Money: Animal { public new void sleep() { Console.WriteLine("원숭이가 자다"); base.sleep(); } } // output : 원숭이가 자다 // 동물이 자다

Sealed

내가 만든 클래스를 다른 곳에 상속하지 못하게 막는 방법
sealed class Animal { public void sleep() { Console.WriteLine("동물이 자다"); } } class Monkey: Animal // 오류 발생 { public void sleep() { Console.WriteLine("원숭이가 자다"); base.sleep(); // 오류 발생 } }

Attribute

코드에 대한 부가정보를 기록하는 것
주석은 인간만 읽을 수 있고 Attribute는 컴퓨터도 읽을 수 있다.
[Attribute명(위치매개변수, 명명된 매개변수=값,…)] 프로그래밍 요소
어트리뷰트는 클래스이므로 생성자를 가질수 있지만 반드시 생성자는 하나이어야만 합니다.

사용자 정의(Custom Attributes)

[System.AttributeUsage(AttributeTargets.Class)] public class MyAttribute : Attribute { //TODO }
[System.AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=true)]
어트리뷰트를 클래스와 메소드 레벨에서 사용할 수 있도록 지정하였으며 중복을 허용합니다.
상속을 지정하지 않는 경우 true값이 설정됩니다.
  • 여러 개의 데이터형에 라벨을 지정하려면 “|” 파이프 연산자로 구분
  • 모든 데이터형에 라벨을 붙이고 싶다면 AttributeTarget.All 사용
사용자 정의 어트리뷰트의 처리과정
  1. 어트리뷰트 클래스 찾는다.
  1. 어트리뷰트의 범위를 체크한다.
  1. 어트리뷰트의 생성자를 체크한다.
  1. 객체의 인스턴스를 생성한다.
  1. 명명 파라미터들을 체크한다.
  1. 명명 파라미터 값으로 필드나 프로퍼티 값을 설정한다.
  1. 어트리뷰트 클래스의 현재 상태를 저장한다.

Object Pooling(오브젝트 풀링)

웅덩이 안에서 필요할때마다 객체를 꺼내서 사용하는것
notion image
오브젝트 생성 → 오브젝트 풀에 넣음 → 꺼냄 → 사용전 초기화 → 사용 → 사용 종료 → 오브젝트 풀에 넣음
다시 사용이 필요할 때 오브젝트를 생성하지 않고 pool에서 꺼낸다.

Generic(제네릭)

코드의 재사용성과 유연성을 향상해주는 도구
  • 클래스나 메소드 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법
  • 클래스나 인터페이스를 정의할 때 타입 매개변수를 사용하여 타입 안정성을 보장하는 기능

사용시기

  1. 여러 데이터 형식에 대해 동일한 로직을 적용해야 할 때
  1. 컬렉션 타입에서 다양한 데이터 형식을 저장하고 관리해야 할 때
  1. 데이터 형식에 따라 다른 연산을 수행해야 할 때
public T GetMaxVale<T>(T a, T b) where T:IComparable<T> { if(a.CompareTo(b) > 0) return a; else return b; } int maxInt = GetMaxValue<int>(5, 10); Console.WriteLine(maxInt); string maxString = GetMaxValue<string>("hello","word"); Console.WriteLine(maxString); // 10 // world

제네릭 제약조건

public class Myclass<T> where T : 제약조건 { // 클래스 내용 } public void MyMethod<T>(T param) where T : 제약조건 { // 메서드 내 }
  1. where T : 클래스명 : T는 특정 클래스또는 해당 클래스를 상속받은 클래스여야 합니다.
  1. where T : 인터페이스명 : T는 특정 인터페이스를 구현한 클래스여야 합니다.
  1. where T : new() : T는 매개변수가 없는 기본 생성자를 가져야 합니다.
  1. where T : struct : T는 값 형식(구조체)이어야 합니다.
  1. where T : unmanaged : T는 비관리 형식이어야 합니다.
  1. where T : enum : T는 열거형이어야 합니다.
  1. where T : delegate : T는 대리자 형식이어야 합니다.
using System; class Program { static void ArrayPrint<T>(T[] Num) { for (int Temp = 0; Temp < Num.Length; ++Temp) { Console.Write("{0} ", Num[Temp]); } Console.WriteLine(); } static void Main(string[] args) { int[] Numbers1 = { 1, 3, 5, 7, 9 }; double[] Numbers2 = { 1.1, 3.1, 5.1, 7.1, 9.1 }; // float형은 f를 붙여야하고, 그냥 실수면 double형이다. string[] Numbers3 = { "일", "이", "삼", "사" }; // 문자열은 ""를 붙여줘야한다. ArrayPrint<int>(Numbers1); ArrayPrint<double>(Numbers2); ArrayPrint<string>(Numbers3); } }

LINQ(링크)

LINQ(Language-INtegrated Query) : 데이터질의(Query)기능을 C#에서 사용할 수 있는 기술

기본구조

  • from : 어떤 데이터에서 원하는 값을 추출할 것인지
  • where : 원하는 값을 추출하기 위한 조건
  • select : 데이터에서 어떤 항목을 추출할 것인
💡
LINQ의 질의 구문은 from키워드로 시작하여 select 키워드로 끝납니다. from 범위 변수 in 데이터 원본
string[] strArr = { "Apple", "Banana", "Car", "Add", "Sum", "Angular" }; var linqResult = from str in strArr where str.StartsWith("A") && str.Length > 3 select str;

Dispose

주로 관리되지 않는 리소스를 해제하는데 사용
  • IDisposable 구현인 인스턴스 멤버를 사용하는 경우에는 Dispose 호출을 계단식 배열하는 것이 일반적입니다.
  • 즉각적으로 해당 데이터를 힙에서 제거하고 싶으면 Dispose를 이용
  • 반드시 public으로 정의

DataTableExtensions 클래스

  • DataTable 클래스에 대한 확장 메서드를 정의합니다.
  • 정적 클래스

DataTable

메모리 내 데이터의 한 테이블을 나타냅니다.

메서드

  • AsDataView(DataTable) : LINQ 사용 DataView 개체를 만들어 반환

DataTable

  • DB를 조회할 때 자주 사용되는 데이터 타입이며 데이터베이스의 테이블과 비슷한 형태를 가지고 있다.
  • 메모리 내 데이터의 한 테이블

컬럼 생성

DataTable data = new DataTable(); data.Colums.Add("name", typeof(string)); data.Colums.Add("data", typeof(DateTime));

데이터 삽입 - 방법1

DataRow row = data.NewRow(); row["name"] = "Mike"; row["data"] = DateTime.Now; data.Row.Add(row);

데이터 삽입 - 방법2

data.Row.Add(new object[] {"Jane",DateTime.Now.AddDays(1)});

DataTable의 데이터 추출방법

DataRow의 컬럼에 해당하는 값을 조회하면 object형태로 반환되기 때문에 ToString이나 Convert를 이용하여 각 걸럼의 데이터 타입에 맞는 형식으로 변환을 해줘야 합니다.
  1. for문을 이용한 데이터 조회
for (int i = 0; i < data.Rows.Count; i++) { String name = data.Rows[i]["name"].ToString(); DateTime date = Convert.ToDateTime(data.Rows[i]["date"]); }
  1. foreach문을 이용한 데이터 조회
foreach(DataRow rows in data.Rows) { String name = data.Rows[i]["name"].ToString(); DateTime date = Convert.ToDateTime(data.Rows[i]["date"]); }

Clone

DataTable의 DataRow를 제외한 컬럼 및 다른 모든 정보들을 그대로 복사합니다.
DataTable new_data = data.Clone();

ImportRow

다른 DataTable의 Row를 그대로 가져옵니다.
DataTable new_data = data.clone(); new_data.ImportRow(data.Rows[1]);

Select

조건에 맞는 특정 DataRow만 선택합니다.
DataRow[] dataRows = data.Select("name = Mike");

Copy

DataTable new_data = data.Copy();

Reset, Clear

data.Reset(); // DataTable을 초기화 data.Clear(); // DataTable의 데이터를 모두 삭

Thread

어떠한 프로그램 내에서 특히 프로세스 내에서 실행되는 흐름의 단위
  • 운영체제의 최소 실행 단위로, 개발자가 직접 제어해야합니다.
  • 생성, 시작, 중지 등의 작업을 개발자가 직접 관리해야 함

Methods

  1. Start() : Thread가 실행, .Thread를 생성할 때 처리할 메서드를 지정하고 호출해야 실행
  1. Join() : 해당 Thread의 처리가 끝날 때까지 대기
  1. Abort() : Thread를 강제로 종료 (안전 보장 X)
  1. Sleep() : Thread를 일시적으로 중지

Task

  • Thread의 일종으로 비동기 코드를 실행할 수 있도록 고안된 것
  • 내부적으로 ThreadPool을 이용하여 Threading을 관리하므로, 개발자가 세부적인 작업을 신경 쓸 필요 없이 로직에 집중할 수 있습니다.
  • Task 클래스는 비동기로 수행할 코드를 Action 델리게이트로 주는 반면 Task는 Func 델리게이트로 준다.

Methods

  1. Start() : Task 실행, 그러나 보통 Task.Run() 메서드를 통해 생성하고 실행
  1. Wait() : Task 처리가 끝날 때까지 대기
  1. Continue With() : Task가 완료된 후에 수행할 작업을 지정
  1. WhenAll(), WhenAny() : 여러 Task의 완료를 기다리는 Task 생성
    1. WhenAll() : 모든 Task가 완료될 때까지 대기
    2. WhenAny() : 주어진 Task 중 하나라도 완료되면 반환
Thread
Task
정의
OS의 최소 실행 단위
비동기 작업을 추상화한 클래스
효율성
직접 제어
ThreadPool 사용, 효율적인 스레딩
사용성
생성,시작,중지 등의 직접 관리 필요
세부 작업 내부 처리, 로직에 집중 가능
코드 복잡성
동기화 문제, 데드락 등 해결 필요
문제를 더 쉽게 처리 가능
반환값
작업 결과 반환 불가
Task<T> 형태로 반환 가능
비동기 지원
직접 지원 불가
async/await 문법 지원

Delegate

메서드를 참조하는 객체로, 메서드의 시그니처(입력 매개변수와 반환 타입)에 대한 정보를 포함
  • 델리게이트를 통해 메서드를 매개 변수로 전달 가능
  • 메서드를 변수에 할당되고 매개 변수로 전달될 수 있는 엔터티로 취급할 수 있도록 합니다.
notion image

Func

반환 값이 있는 메서드를 참조하는 제네릭 델리게이트
  • 마지막 타입 매개 변수는 반환 타입을 나타내며, 나머지 매개 변수는 입력 매개 변수의 타입
notion image

Action

반환 값이 없는(void) 메서드를 참조하는 제네릭 델리게이트
  • 모든 타입 매개 변수는 입력 매개 변수의 타입
notion image

Assembly 클래스

다시 사용 및 버전 지정이 가능한, 공용 언어 런타임 애플리케이션의 자체 설명 빌딩 블록인 어셈블리

Assembly

NET 런타임 환경에서 실행할 수있는 (사전 컴파일 된) 코드 덩어리

Type 클래스

클래스 형식, 인터페이스 형식, 배열 형식, 값 형식, 열거형 형식, 형식 매개 변수, 제네릭 형식 정의 및 개방형 생성 제네릭 형식이나 폐쇄형 생성 제네릭 형식에 대한 형식 선언

TAP(Task 비동기 프로그래밍)모델

  1. 커피 한 잔을 따릅니다.
  1. 팬을 가열한 다음 계란 두 개를 볶습니다.
  1. 베이컨 세 조각을 튀깁니다.
  1. 빵 두 조각을 굽습니다.
  1. 토스트에 버터와 잼을 바릅니다.
  1. 오렌지 주스 한잔을 따릅니다.
동기적으로 준비된 아침은 약 30분 걸림
notion image
비동기적으로 하면 작업이 실행되는 동안 스레드는 계속 작동하고 await키워드는 작업을 차단하지 않는 방식으로 시작한 다음 해당 작업이 완료되면 실행을 계속합니다.
notion image
notion image

Task

  • 스레드 사용으로 인한 오버헤드를 예방하기 위해 스레드 풀을 사용했지만 제약사항으로 인해 작업이 완료되기도 전에 프로세스가 종료될 수 있는 단점을 보완
  • 작업 완료 시점을 알 수 있다.
  • 결과값을 리턴받을 수 있다.
  • 취소/예외처리를 할 수 있다.

this키워드

클래스 외부에서 클래스 내부에 있는 멤버변수에 접근하려면 객체명.멤버변수명으로 접근함
Person p = new Person(); Console.WriteLine(p.name); class Person { public string name = 'test'; }
클래스내 메소드(함수)에서 클래스 멤버변수값을 사용하려면 this를 사용함
Person p = new Person('test'); class Person { public string name; public Person(string name) { this.name = name; // 기존 객체명이었던 p를 대체한것 Console.WriteLine($"이름은{this.name}입니다."); } }

string[] args

  • C# 프로그램(exe 실행 파일)을 콘솔 윈도우(cmd.exe)에서 실행할 때 실행 코드 뒤에 작성한 옵션들은 args에 전달

추상화(Abstract)

  • 상위 클래스와 메서드 앞에 abstract키워드 무조건 추가
  • 상위 클래스에서는 선언만 하고, 하위 클래스에서 무조건 재정의 해야함
abstract class Animal { protected string name; public Animal(string name) { this.name = name; } public abstract string GetName(); } class Dog: Animal { public Dog(string name) : base(name) {} public override string GetName() { return $"강아지 이름: {name}"; } } class Cat: Animal { public Cat(string name) : base(name) { } public override string GetName() { return $"고양이 이름: {name}"; } } Dog dog = new Dog("dog"); Console.WriteLine($"{dog.GetName()}"); Cat cat = new Cat("cat"); Console.WriteLine($"{cat.GetName()}"); // output : 강아지 이름 : dog // 고양이 이름 : cat

얕은 복사, 깊은 복사

notion image
얕은 복사 : 객체를 복사할 때 참조만 복사하는 것
  • 이전 객체의 참조만 복사하기 때문에 힙에서 같은 주소를 가리키게 되고, 이전 객체의 값이 변경되면 복사한 객체의 값도 변경된다.
class classA { public int hp; public classA DeepCopy() { classA clone = new classA(); clone.hp = hp; return clone; } } static void Main(string[] args) { class A m1 - new ClassA(); m1.hp = 10; classA m2 = m1; m1.hp = 0; Console.WriteLine(m2.hp); } // output : 0
깊은 복사 : 객체를 복사할 때 새로운 힙 공간을 할당해 주는 것
static void Main(string[] args) { classA m1 = new ClassA(); m1.hp = 10; classA m3 = m1.DeepCopy(); m1.hp = 0; Console.WriteLine(m3.hp); } // output : 10
m3은 m1과 같은 주소를 가리키지 않고, 힙에서 새로운 공간을 할당받기 때문에 개별적인 객체로 존재하고, m1의 값이 변경되거나 삭제되더라도 영향을 받지 않는다.

Reflection

어떤 Type에 대한 정보를 가져오거나 접근하는 등의 작업을 런타임에 동적으로 수행할 수 있도록 해주는 기능
  • 런타임에서 메서드를 호출하거나 필드의 값을 바꾸는 등의 작업을 할 수 있다.
사용해야하는 이유
애플리케이션을 개발할 때 디버깅 또는 런타임에 알 수 없는 객체의 동작을 분석하기 위해서 또는 외부 라이브러리에 존재하는 클래스 및 메서드를 분석

Dictionary(사전형)

Key라고 불리는 인덱스 번호를 대신해 사용하는 명칭과 Value라고 불리는 값을 세트로 다룬다. ⇒ 연관배열
Dictionary<Key데이터형, Value데이터형> 오브젝트명 = new Dictionary<Key데이터형, Value데이터형>(); var 오브젝트명 = new Dictionary<Key데이터형, Value데이터형>();

스트림(Stream)

프로그램이 주변 장치와 통신하는 수단
스트림은 일련의 데이터가 한 곳에서 다른곳으로 직렬로 이동하는 상태를 가리킨다.
  • 스트림을 통해 이동중인 데이터요소들은 그 순서가 중요할뿐, 적정하게 구조화 시키기 전까지는 어떤 의미를 갖는지 알 수 없다.
  • 스트림의 양 끝단 중 하나는 우리의 코드이고 다른 하나는 데이터를 저장하거나 송수신하는 주변장치
  • 생성된 스트림은 방향이 결정되지 않은, 즉 아직 흐름이 시작되지 않은 상태이다.

데이터 요소의 크기별 스트림 종류

  1. 이진 스트림(Binary Stream)
      • 비트를 나타내는 이진 값이 흐르는 스트림
      • 저수준의 데이터
      • 패킷에 페이로드를 실어 보내는 형식
  1. 바이트 스트림(Byte Stream)
      • 저수준 데이터 통신을 캡슐화하여, 페이로드만을 주고 받는 것처럼 보이는 스트림을 제공
      • 데이터 중 가장 작은 크기인 바이트값으로 환산함

메서드

  • Close() : 현재 스트림을 닫고 현재 스트림과 관련된 소켓과 파일 핸들 등의 리소스를 모두 해제
  • Flush() : 스트림에 대해 모든 버퍼를 지우고 버퍼링된 데이터가 내부 디바이스에 쓰여지도록 함
  • Dispose() : 스트림을 닫고 자원을 해제
  • Read() : 스트림으로부터 특정한 크기의 byte를 읽고 그 위치만큼 position을 이동
  • Write() : byte array를 스트림에 쓰도록 함

연산자 ?. 및 ?[ ] - c# 7.3 이전버전

피연산자가 null이 아닌것으로 평가되었을때만 멤버 액세스 ?. 또는 요소 액세스 ?[] 연산을 피연산자에게 적용하며, 그렇지 않으면 null을 반환
  • anull로 평가되면 a?.x 또는 a?[x]의 결과는 null
  • anull이 아닌것으로 평가되면 a?.x 또는 a?[x]의 결과는 각각 a.x 또는 a[x]

연산자 ?? 및 ??= - c# 8.0 이상버전

null 병합 연산자 ??null이 아닌 경우 왼쪽 피연산자의 값을 반환
그렇지 않으면 오른쪽 피연산자를 평가하고 그 결과를 반환
왼쪽 피연산자가 null이 아닌 것으로 평가되면 ?? 연산자는 오른쪽 피연산자를 평가하지 않는다.
null 병합 할당 연산자 ??=는 왼쪽 피연산자가 null로 계산되는 경우에만 오른쪽 피연ㅅ나자의 값을 왼쪽 피연산자에 대입
왼쪽 피연산자가 null이 아닌 것으로 평가되면 ??= 연산자는 오른쪽 피연산자를 평가하지 않는다.