노력과 삽질 퇴적물
C#: 문법 스캔 (1) 본문
목차
|
|
(1)
|
기본 문법 |
(2)
|
이벤트, 비동기 |
0. 필요한 파일
파일명
|
예시경로 |
VS 2019 [#다운로드] > 16.3 이상 |
(기본경로) |
.NET Core 3.0 [#다운로드] | (기본경로) |
* 해당 포스트는 C# 8.0기반이며, VS 업데이트는 16.8.6입니다.
* 해당 포스트는 JAVA/파이썬 같은 다른 프로그래밍 언어를 알고 있는걸 전제로 생략되는 부분이 있습니다.
1. 문법
1) 상수류
> 상수 선언시 static불가[#MSDN]
> 상수 선언시 static불가[#MSDN]
1
2
|
const int LIMIT_I = 100;//JAVA에서는 final
readonly int m_LIMIT; //멤버변수에서 선언, 초기화는 클래스 생성자에
|
cs |
2) 배열
> C#에서는 참조 타입
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//1차원 배열
long[] potions = new long[3];//고정된 크기로 선언.
string[] itemNames = {"체력 회복", "스태미나 회복", "경험치 물약"};
//2차원 배열
long[,] eventScores = {{1024, 512},{100, -1}};//선언부터 초기화까지 완료.
long[][] eventScoreArr = new long[2][];//가변&2차원 배열
eventScoreArr[0] = new long[10];//공간 선언O. 초기화X.
//그러니 eventScoreArr[0][0]로 호출시 exception.
eventScoreArr[1] = new long[2] {-1, -1};//공간 선언O. 초기화O.
//3차원 배열
long[,,] positions;
|
cs |
3) 문자열
> 정확히는 StringBuilder 클래스를 쓰는 버릇 들이기.
> Immutable 타입 String클래스 Vs. Mutable타입 StringBuilder클래스
: [C#] string + string 과 StringBuilder.Append() 차이
: C#에서 String과 Stringbuilder를 사용하는 경우
-> 문자열 조합시, String형은 참조타입이라 새로운 객체를 생성 + GC
-> 변경 가능한 StringBuilder는 문자열 붙일때 객체 새로 생성X
4) 연산자
> Null-coalescing operator
> nullable 참조 형식 [#MSDN]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
string fromMsg = null;
string receiveMsg = fromMsg ?? "(기본 메시지)";
/*
if(fromMsg == null)
{
receiveMsg = "(기본 메시지)";
}
else
{
//do-nothing.
*/
Console.WriteLine("receiveMsg = "+receiveMsg);
int? resultCode = null;//Nullable 적용.
int receiveCode = resultCode ?? -1;
/*
C# 2.0부터 Nullable<int>처리가 가능.
Integer var = null;와 비슷하게 입력값 처리//JAVA
*/
Console.WriteLine("receiveCode = "+receiveCode );
|
cs |
5) 반복문
> 순차적인 반복문이면 foreach가 권장.
> 순차적인 반복문이면 foreach가 권장.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
string[] itemCodes = ...
... ... ...
for(int idx=0; idx<itemCodes.Length; idx++)
{
//do-something.
}
foreach (tmpItem in itemCodes)
{//CASE. 정방향으로 순차적
//do-something.
}
foreach (tmpItem in itemCodes.Reverse())
{//CASE. 역방향으로 순차적
//do-something.
}
|
cs |
6) 네임스페이스
> 네임스페이스내에 클래스 N개 정의 가능.
> 파일명=클래스명이던 JAVA과 비교시, 네임스페이스 지정은 자유로워
: A.cs에 사용한 네임스페이스를 B.cs에도 동일한 네임스페이스 사용가능.
: A.cs에 사용한 네임스페이스를 B.cs에도 동일한 네임스페이스 사용가능.
> 네임스페이스내 정의내 정의된 클래스를 가져다쓰려면
using (네임스페이스 경로).클래스명
: (JAVA) import (패키지 경로).(클래스명)
(C#) using (네임스페이스 경로).(클래스명)
-> 나름 협업 친화적인 규칙?
7) 구조체&클래스
① 구조체=값 타입(스택) / 클래스=참조 타입(힙)
C#에서 구조체는 상속불가+인터페이스 가능.
② 클래스 멤버
> 필드변수: 기존의 멤버 변수 그거. + 여기서도 접근제한자 적용.
> 프로퍼티: 클래스 멤버 변수에서 함수처럼 [이름(...)]의 괄호가 없지만,
그 변수내에 get/set 정의 가능.
8) 함수 파라미터
① Pass by Value
> 함수인자에 변수값을 복사해서 전달.
> 함수에 값을 입력한다고 해서 함수 호출 이후 함수에 넣었던 변수값 변경X
② Pass by Reference
> 함수 인자에 ref/out키워드를 덧붙여 사용.
1
2
3
4
5
6
7
8
9
10
11
|
private void Prefix(ref int argA, out int argB)
{
... ... ...
//do-somethging.
}
... ... ...
int codeForRef = 100;
int codeForOut;//초기화 불필요.
Prefix(codeForRef, out codeForOut);
//함수 호출로 codeForRef와 codeForOut의 값 변경된거 확인 가능.
|
cs |
③ Named 파라미터
> C# 4.0부터 지원.
> 기존에는 함수 인자 입력시, 정의된 순서대로 값을 입력했다면
함수를 사용할때 key-value처럼 인자를 입력.
함수를 사용할때 key-value처럼 인자를 입력.
④ Optional 파라미터
> C# 4.0부터 지원.
> 자바스크립트에도 있는 함수 인자 기본값 지정
1
2
3
4
5
6
7
8
9
10
|
private void doFunction(int argA, int argB, int argC=-1)
{
... ... ...
//do-something.
}
//함수 호출시 입력한 인자가 달라보여도 동일 함수 호출.
doFunction(2021, 2);
doFunction(2021, 2, 28);
|
cs |
⑤ params 키워드
> JAVA로 치면 '가변인수'(Varargs)?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/*
//Test.java
void sendMsg(String... msgs)
{//msgs: 가변 배열인 함수 인자
... ... ...
sendMsg("test1");
sendMsg("test2_1", "test2_2");
*/
private void SendMsg(params string[] msgs)
{
... ... ...
}
SendMsg("test1");
SendMsg("test2_1", "test2_2");
|
cs |
⑥ Partial 키워드
> 다른 코드 파일이여도 동일한 클래스를 작업이 가능케 하는 키워드
8) 전처리기 지시어
① 조건별 컴파일
1
2
3
4
5
6
7
|
#if ENV_DEBUG
//do-something.
#elif ENV_QA
//do-something.
#else
//do-something.
#endif
|
cs |
② region
1
2
3
4
5
6
7
8
9
10
11
12
|
/*
함수나 멤버들 그룸 상하에
//START. func.DoXxx
... .... ...
//END. func.DoXxx
수동으로 하던거에 아예 접단 지원하는 지시어.
*/
#region Public DoXxx
public void DoActionA() { }
public void DoActionB() { }
#endregion
|
cs |
9) static
> 정적 속성/필드: 프로그램 실행후 소속된 클래스가 처음 사용될때 초기화+동일한 메모리 사용.
> 정적 함수: [클래스명.함수명(...)]으로 호출&사용. 인스턴스 객체(혹은 객체화된 클래스)에서 호출 불가.
> 정적 클래스: 생성자 X, 객체화 불가 (싱글톤이 아닌 Utility용 클래스에 쓰던거와 동일)
10) 제네릭
> 클래스명<T>
: HashMap<>선언해서 쓸때 다양한 타입 허용하는 그거. (용어도 동일)
11) 익명타입 변수
> C# 3.0부터 지원.
> 변수 자료형을 var로 쓰는건데, C#에서는 읽기전용이라 함.
12) 확장 매소드(확장 함수)
> C# 3.0부터 지원.
> 굳이 String/Integer 클래스를 상속받아 추가 기능을 넣을 필요없이,
[네임스페이스.정적_클래스.정적_함수]로 정의해서
필요한곳에서 접착해서 사용.
1) 한국어
.NET Core 3.0의 새로운 기능 | Microsoft Docs
[C#] 왜 partial class를 사용하는걸까요?
필요한곳에서 접착해서 사용.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
// 확장 매소드(or 확장 함수)가 정의된 CS파일.
namespace Com.Muteukgi.ExtensionMethods
{
public static class ExtenedFunction
{
public static int DoActionType1Ext(this int arg1)
{
int result = -1;
//do-something.
return result;
}
public static int DoActionType2Ext(this int arg1, int arg2)
{
int result = -1;
//do-something.
return result;
}
}
}
//다른 CS파일에서
using Com.Muteukgi.ExtensionMethods;
... ... ...
int test = 100;
int tmp = -1;
tmp = test.DoActionType1Ext();
tmp = test.DoActionType2Ext(2021);
|
cs |
2. 이벤트, 비동기
1) 이벤트 핸들러
1
2
3
4
5
6
7
8
9
10
11
|
... ... ...
xxx.Click += new EventHandler( ActionHandler );//핸들러 등록
... ... ...
... ... ...
xxx.Click -= new EventHandler( ActionHandler );//핸들러 해제.
}
private void ActionHandler (object sender, EventArgs e)
{
//do-something.
}
|
cs |
2) 델리게이트(delegate)
> 예시나 설명을 보면,
: 상위 기능 함수(?) 내부에서 입력값별로 if-else나눈 블록에서 호출되는 세부 기능을 하는 함수 호출하는걸 도와주는 격.
: 상위 함수의 함수 인자가 delegate로 선언된 변수이면 그 인자에는 함수명을 변수처럼 입력하고, 상위 함수 내에서는 delegate형 변수는 코드상 입력된 함수의 코드대로 작동.
//지명된 다른 매소드 이름에 맞게 매소드 연기.
> 함수를 참조하는 변수로 함수 포인터랑 비슷하다는 설명도 있음.
: 함수 포인터 비슷하다 하지만, 델리게이트 1개-함수1개 이상 가능.(델레게이트 체인)
: 델리게이트 호출시 체인이 걸린 함수들이 순차적?동시에 실행? //세부 동작 확인 필요.
> 인스턴스/정적 함수 모두 가능.
> 제네릭 타입도 허용.
> 실질적인 용도는 콜백 매소드라 함.
3) 무명 함수(혹은 익명 함수)
> 이벤트 핸들러등에서 반복 사용될게 없는 코드를 함수 선언해서 쓰지않고, 내부 동작 자체를 그대로 붙여넣음.
1
2
3
4
5
6
7
8
9
10
11
|
/*
EventHandler에 쓰이는 함수의 인자는 (object sender, EventArgs e)인데,
익명형은 경우에 따라 함수인자도 생략된 형태O
*/
xxx.Click += new EventHandler(delegate(object s, EventArgs a) { /* do-something. */ });
xxx.Click += (EventHandler) delegate(object s, EventArgs a) { /* do-something. */ };
xxx.Click += delegate(object s, EventArgs a) { /* do-something. */ };
xxx.Click += delegate { /* do-something. */ };
|
cs |
4) 람다
1
2
3
4
5
|
//type1.
(argA, argB) => { /* do-something */ };
//type2.
(int argA, string argB) => { /* do-something */ };
|
cs |
5) async&await
> C# 5.0부터 지원된 비동기 관련 기능.
: 비동기 함수에도 반환값 처리 가능(JAVA로 치면 Future로 스레드에서 반환값 받는거.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
/*
In JAVA
ExecutorService service = Executors.newSingleThreadExecutor();
Future<T> future = service.submit(task);
REF. https://deep-dive-dev.tistory.com/6
*/
... ... ...
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
DoAction();
}
private async void DoAction()
{
Debug.WriteLine("DoAction(1) " + Thread.CurrentThread.ManagedThreadId);
int tmp = -1;
tmp = await DoAsync(10); //async 키워드 있는 함수로 비동기 처리
Debug.WriteLine("tmp: " + tmp );
var testTask = Task.Run( ()=>DoFunc(10) );//async 키워드 없는 함수로 비동기 처리
tmp = await testTask;
Debug.WriteLine("tmp: " + tmp );
Debug.WriteLine("DoAction(2) " + Thread.CurrentThread.ManagedThreadId);
}
private async Task<int> DoAsync(int arg)
{
Debug.WriteLine("DoAsync, " + Thread.CurrentThread.ManagedThreadId);
... ... ...
return result;
}
private int DoFunc(int arg)
{
... ... ...
return result;
}
|
cs |
기타. 참조자료
1) 한국어
.NET Core 3.0의 새로운 기능 | Microsoft Docs
[C#] 왜 partial class를 사용하는걸까요?
'📂기초 및 세팅 note > 언어. C# 계열' 카테고리의 다른 글
C#: 문법 스캔 (3) (0) | 2021.07.16 |
---|---|
C#: 문법 스캔 (2) (0) | 2021.07.16 |
이론: 닷넷 프레임워크(.NET Framework) (0) | 2016.08.21 |
C#: 기초문법 (0) | 2015.12.21 |