참고 자료: MS Document
- C#이 생각보다 자료가 많이 없어서 그냥 공식문서 보고 정리하려고 한다.
일단은공식문서
상의 구조를 따라가려고 하는데 내용은 내 맘대로 써질 예정- 본질이 iOS 개발자라 많이 비교하면서 학습을 진행할 예정이다.
- @>--- 이런 기호와 함께 '기울임', '작게' 표시 되면 개인적인 생각이다.- 당연 이건 다른 언어를 했던 사람들이 C# 공부시 그나마 조금 편하라고 만들어 보는거지 아예 코드 짜는 사람이 처음이라면 이해 안될 수 있는다.
- 이해 안되는건 뒤에 나올 내용이 앞에 나와서 그러는거니까 첨보는 단어면 일단 넘어가면 뒤에 다시 나온다.
int num = 5;
float fNum = 1.0f;
double dNum = 1.0;
bool flag = false;
struct, class, interface, enum, record
.NET 클래스 라이브러리
- 명명 규칙
- 계층 구조를 의미하는 스키마 이름을 지정하는데
. 구문
을 사용- 이 방식을 사용하면 관련 형식을 네임스페이스로 그룹화해 보다 쉽게 검색, 참조 가능
System.Collections.Generic.List< T > 이런 구문이 있다면 System.Collections.Generic 네임스페이스에 속하는 List< T >의 형식을 나타내는것
- System 네임스페이스
- 위에서 타입들 나열해놨으니 그것들 확인해볼것
3.데이터 구조체
- 다양한 데이터 구조 집합이 포함되어있는데 대부분
컬렉션
이지만 다른 형태도 존재
- Array : idx 로 접근 가능한 개체 배열 -> 고정 적 크기 존재
- List : idx 로 접근 가능한 개체 목록 -> 크기가 자동 조정
- Dictionary<TKey,TValue> : 키를 통해 값에 엑세스 가능 -> 크기 자동 조정
- Uri : 개체 표현을 제공하며 URI 부분에 쉽게 엑세스 가능
- DateTime : 날짜와 시간으로 표시된 시간
@>--- 뭐 이렇게 있다고는 하는데 대게 List랑 Dictonary를 자주 사용할 것 같다.(동적 크기 변경 짱..)
- 유틸리티 API
- 여러 중요 작업 기능 제공하는 유틸리티 API 집합이 포함
- HttpClient : URI로 식별되는 리소스에서 HTTP 요청을 보내고 HTTP 응답을 받기 위함
- XDocument : XML 문서 로드, LINQ 사용해 쿼리하기 위함
- StreamReader / StreamWriter : 파일 읽기/ 쓰기
2가지
기초 사항을 이해해야 함상속
원칙을 지원값
또는 참조
타입으로 정의사용되는 모든 타입들은 모두 System이라는 네임스페이스에 구성되어있는데
타입들이 포함된 네임스페이스는 타입이 값인지 참조인지 관련은 없다.
멤버
다.참조
타입이다.값
타입이다.실제
데이터가 포함된다.복사
된다. 값
일 수도 참조
일 수도 있다.할
데이터를 저장한다.않을
데이터를 저장한다.직접
포함된다.인터페이스
를 구현할 수 있다.struct
키워드를 사용해 고유한 사용자 지정 값 타입을 만들며, 일반적으로 구조체는 다음과 같이 소규모 관련 변수 집합의 컨테이너로 사용한다.public struct Coords
{
public int x, y;
public Coords(int x, int y)
{
this.x = x;
this.y = y;
}
}
public enum DBMode
{
Create = 1,
Read,
Update,
Delete,
}
class, record, delegate, 배열, interfacer 로 정의된 형식이다.
해당 참조 타입의 변수 선언시에는 해당 타입의 인스턴스를 할당하거나 new 연산자를 사용해 생성할 때까지 값 null을 포함한다.
참조 형식은 상속을 완벽하게 지원하는데 class 만들 떄 sealed
로 정의되지 않은 기타 인터페이스 또는 클래스에 상속할 수 있다.
@>--- 이게 뭔소리일까.. 알아봄 (이해 안되면 일단 넘겨도 됨)***
클래스, 구조체, 레코드 공식문서 는 여길 참고
상속은 공식문서 여길 참고
class 만들 떄
sealed
로 정의되지 않은 기타 인터페이스 또는 클래스에 상속할 수 있다?
@>--- 이게 무슨 소리일까 한 번 고민해봅시다.
- 일단 참조 타입은 class, interface, delegate, array, string을 포함하며 참조형식은 힙에 저장되며, 변수는 해당 객체의
메모리 주소
를 가진다.- 참조 타입은 상속을 완벽하게 지원하며 C#의 경우에는
단일 상속
을 지원한다. 즉, child 는 1 parent 만 상속할 수 있다.
- 하지만, 인터페이스는
다중 상속
이 가능하며, 틀래스는 여러개의 인터페이스를구현
할 수 있다.- 그래서 참조 타입은 상속을 통해 기능의 확장과 다형성을 구현할 수 있다.
그럼
sealed
키워드는 뭘까?
해당 키워드는 클래스 선언 앞에 사용되어, 해당
클래스를 더 이상 상속할 수 없도록
한다.즉, 해당 키워드로 선언된 클래스는
상속의 마지막 단계
로 다른 클래스가 이를 상속받아 확장할 수 없다.public sealed class FinalClass { }
- 근데 해당 키워드는 메서드나 속성 앞에서도 사용할 수 있으며, 이때는 상속 받은 클래스에서 해당 메서드를 재정의 할 수 없게 한다.
- 이때는
override
키워드와 함께 사용해야 한다.virtual
키워드는 해당 멤버가 child 클래스에서 override 될 수 있음을 나타낸다.
- 즉 기본 클래스에서 선언된 멤버를 자식 클래스에서 재정의해 다형성을 구현할 수 있게 하는 중요한 키워드이다.
- 해당 키워드를 사용하는 멤버는 기본적으로 기본 클래스에서
구현되어
있어야 한다.- 그냥
public virtual void Show();
이렇게 넘기면 안됨!!!- 구현 예시는 아래와 같다.
class BaseClass { public virtual void Show() { Console.WriteLine("Hello World"); } } class DerivedClass : BaseClass { public sealed override void Show() { Console.WriteLine("Hello SUB World"); } } class SubDerivedClass: DerivedClass { // Show 메서드 재정의 불가 }
근데 여기서 override 키워드가 나온 김에 다른 키워드를 하나 더 보자면
abstract
가 있다.
이 키워드는 virtual 메서드와 비교를 해보면 된다.
virtual 키워드 같은 경우에는
기본 클래스에서
구현을 해야지 사용이 가능한데 이 키워드로 선언된 메서드는 기본 구현이 필요 없다.
- 단, 이렇게 선언된 메서드의 경우 이 메서드의 클래스를 상속한
자식
클래스는반드시
해당 메서드를구현
해야 한다.
- 마치 인터페이스의 디폴트 구현 안된 메서드와 같은 기능같다.
구현 예시는 위에서 구현했던 코드들을 재활용해본다.
public abstract class BaseClass { public virtual void Show() { Console.WriteLine("Hello World"); } public abstract void Log(string msg); } class DerivedClass : BaseClass { public sealed override void Show() { Console.WriteLine("Hello SUB World"); } public override void Log(string msg) { Console.WriteLine($"{msg}"); } } class SubDerivedClass: DerivedClass { // Show 메서드 재정의 불가 }
class MyClass
{
public int classNum2 = 2;
public int classNum { set; get; }
}
MyClass myClass = new MyClass();
MyClass myClass2 = myClass;
없다
근데 이거 개념적으로는 swift에서 protocol이랑 비슷한거 같다.
- 그렇게 생각하는 이유로는 인터페이스의 경우에는 하나 이상의 추상적인 요소들을 포함하는
추상적
인 타입이라는 정의와- 클래스나 구조체가 특정 기능을 구현하도록
강제
하고- 인스턴스 할 수 없기에 인터페이스
자체의 객체
를 생성할 수없고
- 모든 멤버들이 일단 public이며(
다 구현해야
한다는 것), 구현부가 없다.
- 근데 이거도 보니까 C# 8.0 부터는 기본 값을 넣을 수 있음
- 그렇다는거는 이걸 구현하는게 강제 된다는게 아님
- 만약
int Add(int a, int b);
를 인터페이스로 넣어놨는데 만약 디폴트 구현을 안해놨으면 이 인터페이스를 사용하는 클래스에서 해당 함수들을 계속 구현해야 하는데..
디폴트로return a+b
를 구현해두면 매번 구현 할 필요 없이 저 동작을 할 수 있게 된다.다중
상속이 되기에 클래스나 구조체는여러 개
의 인터페이스를 구현할 수 있다.그런고로 Interface == Protocol 이라는 생각을 한다.
구현은 다음과 같다.
public interface IMyInterface { void Log(string msg); void LogError(string error); } class InterfaceClass : IMyInterface { public void Log(string msg) { Console.WriteLine($"{msg}"); } public void LogError(string error) { Console.WriteLine($"{error}"); } } class Program { static void Main(string[] args) { IMyInterface myInterface = new InterfaceClass(); } }
가비지 수집
은 회수를 수행하는 자동 메모리 관리 기능으로 고도로 최적화되고 대부분에서 성능 문제를 일으키지 않는다.참조
타입이다.int[] nums = [1,2,3,4,5];
리터럴(Literal) 이란??
- 코드에서 직접적으로 값을 표현하는 고정된 값을 말한다.
즉, 프로그램 실행 중 변하지 않는상수
값을 의미한다.
근데 이게 진짜 상수를 의미한다기보다는어떤 데이터 타입
인지에 따라 다르게 처리된다.
즉, 각 리터럴은 기본적으로 자신의 데이터 형식을 갖고 있고 필요에 따라 명시적으로 지정할 수 있다.- 그니까 이게 뭔소리냐면... 변수 생성 할떄 값 넣을때 그거! 그게 리터럴 값이라는 소리다
int num = 1; long lNum = 1L; uint uNum = 1U; double dNum = 1.0; float fNum = 1.0f; string str = "abc"; char chr = 'abc'; bool flag = true; string s = "The answer is " + 5.ToString(); Type type = 12345.GetType();
public T outT<T>(T num)
{
return num;
}
제네릭 타입
이건 swift에도 있는 그 제네릭 생각하면 된다.
var
키워드를 사용해 클래스 멤버가 아닌 로컬 변수를 암시적으로 형식화할 수 있다.var 키워드
- var 키워드의 경우에는 프로그램이 변수나 상수 선언시 형식을 유추해서 저장을 할 수 있게 하는 키워드이다.
전역변수로 생성할 수 없으며
지역변수로 class나 메서드 내부에서 생성을 해서 사용 할 수 밖에 없다.- 당연하게도 형식 추론을 해야 하는 키워드 이므로 성능에는 좋지 않은 결과를 만들어 잦은 사용은 좋지 못하다
- 만능처럼 보일 수 는 있는데 너무 자주 쓰면 휴먼에러도 발생할 수 있고 좋지는 않으나 쓸 수 밖에 없거나 쓰는게 좋은 경우도 당연하게 있다.
// 이렇게 할것을 List<int> list = new List<int>(); // 이렇게 할 수 있다. var list2 = new List<int>();
- 형식 추론이 나쁜 이유가 추론을 해야하니까 그 추론을 하기 위한 작업이 따로 들어가야 해서 그 동작에 대한 시간이 걸리니 응용프로그램이 느려지거나,
- 그에 따른 이슈가 발생하는건데 위에 처럼 애초에
타입을 명시하지 않지만 추론으로 확정
하는 방법을 사용하면 꽤 보는게 편해질 수 있다.- var 의 사용을 남용하는건 좋지 않지만 적절히
힌트
를 줘가면서 사용하는건 나쁘지 않아 보인다.당연하게도 이런건 swift에도 비슷한 화제가 나온적이 있다.
없다
?
를 추가하면 null 허용 값 타입을 만들 수 있다.변수의 컴파일 시간과 런타임 형식은 서로 다를 수 있다.
이게 컴파일 시간 형식은 소스 코드에서 선언되거나 유추되는 변수의 형식인데, 런타임 형식은 해당 변수에서 참조하는 인스턴스의 형식이다.
string msg = "Hello My name is SEAN";
IEnumerable<char> someChar = "Hello My name is SEAN";
위의 코드에서 보면 두 변수의 런타임 형식은 전부 string 인데, 컴파일 시간은 처음은 object, 두번째 줄은 IEnumerable 이다.
두 형식이 변수에 대해 다른 경우 컴파일 시간 형식과 런타임 형식이 적용되는 경우를 이해 하는 것이 더 중요하다.
@>--- 근데 이거 좀 코드 짜는데 딱히 막 이렇게까지 따져서 하기에는 지금
할건 아닌거 같으니 여기까지..