관리 메뉴

KorSA

Mosh의 Udemy C# 강의를 듣고나서 끄적이는 메모 본문

Study Memos/C#

Mosh의 Udemy C# 강의를 듣고나서 끄적이는 메모

Praiv. 2019. 10. 5. 23:54
320x100

[ 초급 ]

 

1. 

Class 들을 묶은 개념이 Namespace이다.
Namespace 들을 묶은 개념이 Assembly이다. Assembly는 DLL 형태나 EXE 형태로 존재한다. 
Assemly 들을 묶은 개념이 Application이다.

 


2.

 C#에서 코딩할 때 나오는 byte, short, int, long, float, double, decimal, char, bool 키워드들은 C#에서 사용하는 primitive type이다. 

Byte, Int16, Int32, Int64, Single, Double, Decimal, Char, Boolean 키워드들은 .NET 언어군(C#, F#, VB ..)에서 사용하는 .NET의 primitive type이다.

 


3. 

C#에서 "3.4" 와 같이 실수형 값을 입력할 때 default는 double 형이다. float 형으로 사용하려면 "3.4f", decimal 형으로 사용하려면 "3.4m" 처럼 뒤에 알파벳을 붙여줘야 한다.

 


4. 

String, Array, Enum, Class는 Non-primitive type이다.

 


5.

checked 키워드는 overflow를 체크하기 위해 사용한다.

 

 


[ 중급 ]

 

1. 

static 을 사용하는 이유 중 하나는 Singleton 개념을 표현하기 위함이다.

 


2. 

클래스는 파라미터가 다른 생성자 여럿을 가질 수 있고 기본 생성자의 호출도 가능하다.
ex)
public MyClass(){}
public MyClass(int id) : this() {}

 


3. 

상속(Inheritance)를 사용할수록 클래스의 coupling이 증가한다. 이를 tight coupling이라 하고, 한 클래스의 변경이 다른 클래스에 영향을 주는 강도가 강함을 뜻한다.
상속의 tight coupling을 줄이기 위해 Composition을 사용한다. Composition은 loose coupling의 장점이 있다.
Inheritance는 Is-a 의 관계이고, Composition은 Has-a 의 관계이다.

 

ex)
Animal 클래스를 상속받은 Dog 클래스와 Bird 클래스가 있다고 가정해보자.
Dog와 Bird 둘 다 Animal 클래스를 상속받는다.
그런데 문제가 생겼다.
Bird는 Walk()와 Fly() 속성이 있다. 반면 Dog는 Walk() 속성밖에 없다.
Animal 클래스를 상속받는 Fish 클래스를 새로 만들 일이 생겼다고 하자.
Fish는 Walk() 속성이 없고 Swim() 속성이 있다.
그렇다면.. 정녕 Animal 클래스에서 Walk(), Fly(), Swim() 속성을 모두 구현해야 되는거냐...
Animal 클래스를 고치다가 혹시 무슨 문제가 발생하진 않을까?
자식 클래스 하나 추가되었다고 부모 클래스가 바뀌어 버리는 결과를 낳는다.
부모 클래스가 바뀌면 이를 상속하고 있던 나머지 자식 클래스들도 모두 영향을 받게 된다.
아무일 없을 거라고 장담할 수 있는가?
이것이 상속의 문제점이다. 클래스끼리 강하게 얽혀있어서 변경에 대해 유연하게 대처하지 못한다.

여기서 Composition 개념이 능력을 발휘한다.
Composition은 인터페이스를 사용하여 능력을 부여해주는 개념으로,
Walk() 속성이 필요한 클래스는 IWalkable 인터페이스를 구현하도록 요구한다. 마찬가지로,
Fly() 속성이 필요한 클래스는 IFlyable 인터페이스를 구현하도록 하고,
Swim() 속성이 필요한 클래스는 ISwimmable 인터페이스를 구현하도록 한다.

그러면 부모 클래스인 Animal 클래스의 수정 없이 Dog는 걸을 수 있고, Bird는 날 수 있고, Fish는 헤엄칠 수 있다.


4. 

자식 클래스는 base 키워드를 통해 부모 클래스를 호출할 수 있다.

 


5.

자식 클래스를 부모 클래스로 캐스팅하는 걸 Upcasting이라 하고, 부모 클래스를 특정 자식 클래스로 캐스팅하는 걸 Downcasting 이라 한다.

 


6. 

부모 클래스의 virtual 함수는 자식 클래스에서 해당 함수 앞에 override 키워드를 붙임으로써 재정의할 수 있다.
virtual 함수의 경우 부모 클래스에서 이미 정의가 이루어진다.
반면, abstract 함수의 경우 부모 클래스에서 정의하지 않은 채로 존재한다. 보통 자식 클래스에서만 알 수 있는 특정 정보가 있어야만 정의할 수 있는 함수의 경우 abstract 함수로 쓴다.
abstract 함수가 있는 부모 클래스는 클래스 선언 앞에 abstract 키워드를 붙여야 하고, abstract 클래스를 상속받은 자식 클래스는 반드시 abstract 함수를 자신이 정의해야한다. 
이 때에도 자식 클래스는 이 함수 앞에 override 키워드를 붙여야 한다.

 


7. 

sealed 키워드는 더 이상 상속하지 않을 클래스를 정의할 때 클래스 선언 앞에 붙인다. 이는 약간의 성능 향상을 가져오지만 anti-pattern 이기에 그리 추천되진 않는다.

[ 고급 ]

1. 

Indexer를 사용하면 내가 만든 클래스도 배열처럼 [ ] 으로 접근할 수 있다.

 


2. 

제네릭 클래스를 만들 때 T의 인터페이스 등을 지정해 줄 수 있고, new() 키워드로 T가 reference 형임을 선언할 수 있다.

 

ex) public class Utilities where T : IComparable, new()

 


3.

Delegate는 함수에 대한 포인터라고 볼 수 있고, 어떻게 함수를 불러야 할지를 알고 있는 객체이다.
즉, 함수의 프로토 타입을 알고 있는 객체이며, 같은 프로토 타입을 가지는 여러 함수들을 collection으로 갖고 있을 수 있다.

 


4.

Delegate는 디자인의 확장성과 유연성을 위해 사용한다. 주로 디자인에 event가 사용될 때 함께 쓰인다.

 


5.

Action, Func 등의 응용도 있다.

 


6.

기존에 마소 느님이나 다른 라이브러리에서 만들어 놓은 클래스를 확장하여 사용할 수 있다. (Extension Methods)
LINQ도 그 예 중 하나이다.

 


7.

LINQ는 함수를 호출하는 형태로 쓸 수도 있고, sql 구문을 적듯이 쓸 수도 있다.
sql 구문도 결국 컴파일러 내부적으론 LINQ 함수를 호출한다.
LINQ는 Objects, Entities(DB), XML, ADO.NET Data Sets 등에 사용된다.

 

 

8.

NULL 관련된 연산자로 ??, ? 가 있다.

 

ex) DateTime? d1;
     DateTime d2 = d1 ?? DateTime.Today;
     d2 = d1?.Value;

 


9.

dynamic 키워드는 static language인 C#에서 변수의 타입을 선언하지 않게 해주는 키워드이다.

 

ex) dynamic a = "abc";

 


10.

Reflection은 객체의 GetType() 함수를 호출하여 dynamic 변수를 다루듯 사용할 수 있다.
Reflection은 가독성이 그리 좋진 않다.

 


11.

Reflection, dynamic은 compile time에 에러를 거르지 않기 때문에 runtime 에서 오류가 난다.
개인적으론 static language의 특성만 사용할 때에 비해 코딩 속도는 빨라지지만 안정성은 좀 더 떨어지지 않을까 싶다.

 


12.

Exception 클래스를 상속받아 나만의 custom Exception을 만들어 사용할 수 있다.

 


13.

Web에 접근할 때, 파일이나 데이터베이스에 액세스할 때, 이미지를 처리할 때 등등에 Asynchronous 특성을 사용하면 반응성을 향상시킬 수 있다.
C#에선 .NET 4.5부터 async, await 키워드를 제공한다. (기존의 전통적인 방식은 Multi-threading, Callback 을 사용하는 방식이었다.)

 


14.

await을 쓰려면 async로 선언된 함수 내부에서 사용해야 한다.

 

ex) A 함수에서 async B 함수를 호출하였다고 가정해보자.
B의 어느 지점에선 await 키워드를 사용할 것이다.
프로그램의 제어는 B 함수 내부에서 순차적으로 진행되다가 await 키워드를 만나는 순간 A 함수로 리턴한다.
await 키워드가 하는 역할은 "야, 내가 좀 시간이 걸리니까 너 할 일 먼저 하고 있어. 난 Task 하나 파서 따로 작업하고 있을게. 그리고 이거 끝나면 B 함수의 나머지 부분들은 내가 알아서 수행할게."
라고 말해주는 것이다.
프로그램은 이 덕분에 "아 그래? 그럼 난(기존의 Main Task) A 로 돌아가서 내 할일 하러 간다. 뒤를 부탁해~" 하고 B를 떠나간다.

Mosh는 위의 mechanism을 await을 기준으로 함수가 반으로 갈린다고 표현하였는데, 그렇게 헷갈리던 async - await이 드디어 이해가 되었다.

 


15. 

C#을 공부했으면 이제 나의 앞에는 크게 3갈래의 길이 있다.
1) Windows Store Apps
    Windows RunTime (WindowsRT)
2) Windows Desktop Apps
    Windows Presentation Foundatino (WPF)
    Entity Framework
3) Web Apps
    ASP.NET MVC
    Entity Framework

Mosh는 각 분야가 각각 공부할 것들이 정말 많으므로 한 분야를 정해서 집중적으로 공부하길 권한다.

 


16. 기초, 기초, 기초
알고리즘, 자료구조, OOP, Clean Coding, 리팩토링은 실력 있는 개발자로 성공하기 위한 필수 조건이다. 꼭 공부해라. (Mosh의 마지막 말...)


 


728x90
728x90
Comments