목차
(1)
 이론
(2)
 TCP
(3)
 소켓


* 주요 참조자료상, 닷넷 기반 TCP/IP, UDP입니다.


 
 
 
1. 이론
 
1) TCP
> TCP클라이언트와 TCP Listener 클래스가 사용된.
 
 
2) UDP
> 연결지향인 TCP와 달리, UDP는 속도를 중시한 처리가 중요한 프로토콜.

* TCP클라이언트/Listener 클래스와 UDP클라이언트 클래스는 내부적으로 소켓 클래스 사용하고, 소켓 클래스는 low-level 소켓 프로그래밍 지원.
* 해당 포스팅에서는 UDP 예시는 생략.





2. TCP


1) 클라이언트 사이드
> 인코딩/디코딩 절차상, 예제의 문자열뿐 아니라 이미지같은 미디어 전송도 가능.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using System.Net.Sockets;
... ... ...
 
//STEP.1    IP주소와 포트번호
TcpClient tClient = new TcpClient("127.0.0.1"80);
 
string requestMsg = "2021_05_17";
byte[] encodedBytes = Encoding.ASCII.GetBytes(requestMsg);//인코딩처리.
 
//STEP.2    NetworkStream
NetworkStream nwStream = tClient.GetStream();
 
//STEP.3    NetworkStream.Write
nwStream.Write(encodedBytes, 0, encodedBytes.Length);
 
//STEP.4    NetworkStream.Read
byte[] recivedBytes = new byte[1024];
int nbytes = nwStream.Read(recivedBytes, 0, recivedBytes.Length);
string resultMsg = Encoding.ASCII.GetString(recivedBytes, 0, nbytes);
 
//STEP.5    접속종료
nwStream.Close();
tClient.Close();
cs


(HTTP 프로토콜처럼)연결 끊길때까지 처리하려면 STEP.4에서

1
2
3
4
5
6
7
8
9
byte[] recivedBytes = new byte[1024];
int nbytes;
MemoryStream mStream = new MemoryStream();
while ((nbytes = nwStream.Read(recivedBytes, 0, recivedBytes.Length)) > 0)
{
     mStream.Write(recivedBytes, 0, nbytes);
}
byte[] resultBytes = mStream.ToArray();
mStream.Close();
cs
MemoryStream으로 루프 돌려야.



2) TCP Listener를 이용한 비동기 서버

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
38
39
40
41
42
43
44
static void Main(string[] args)
{
  TestTcpAysnc().Wait();
}
... ... ...
async static Task TestTcpAysnc()
{
  int port = 2021;
  IPAddress targetAddress = IPAddress.Parse("127.0.0.1");
 
  TcpListener tListener = new TcpListener(targetAddress, port);
  try
  {
    tListener.Start();
  } catch(SocketException e) {
    //do-something.
  } finally {
    tListener.Stop();
  }
 
  while (true)
  {        
    TcpClient tcpClient = await tListener.AcceptTcpClientAsync().ConfigureAwait(false);
    Task.Factory.StartNew(doStreamAsync, tcpClient);//to new thread
  }
}
 
async static void doStreamAsync(object argObj)
{
  TcpClient tcpClient = (TcpClient)argObj;
  NetworkStream nwStream = tcpClient.GetStream();
 
  String msg = null;
  byte[] buff = new byte[1024];//512, 1024, 2048 ...
  var nBytes = await nwStream.ReadAsync(buff, 0, buff.Length).ConfigureAwait(false);
  if (nBytes > 0)
  {                
    msg = Encoding.ASCII.GetString(buff, 0, nbytes);       
    await nwStream.WriteAsync(buff, 0, nbytes).ConfigureAwait(false);
  }
 
  nwStream.Close();
  tcpClient.Close();
}
cs





 

3. 소켓
 

1) 클라이언트 사이드

> Connect->Send->Receive->Close
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
38
39
40
41
42
43
using System.Net;
using System.Net.Sockets;
... ... ...
public class TestSocket
{
    public static void Main(string[] args)
    {
        int port = 8080;
        Socket socket = null;
        byte[] requestBytes = Encoding.ASCII.GetBytes( string.Empty );
        byte[] responseBytes = new byte[8192];
 
 
        //STEP.1 연결관련 객체
        IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("172.0.0.1"), port);
        socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
 
        //STEP.2 서버에 연결
        socket.Connect(endPoint);
 
 
        while ((cmd = Console.ReadLine()) != "q")
        {
            requestBytes = Encoding.UTF8.GetBytes(cmd);
 
            try{
                //STEP.3 리퀘스트
                socket.Send(requestBytes, requestBytes.Length, 0);
 
                //STEP.4 리스폰스
                int responseInt = socket.Receive(responseBytes, responseBytes.Length, 0);
                string response = Encoding.UTF8.GetString(responseBytes, 0, responseInt);
                Console.WriteLine(response);
            } catch(SocketException except){
                Console.WriteLine(except.ErrorCode);
                //do-something
            }
        }
 
        //STEP.5
        socket.Close();
    }
}
cs


2) 서버 사이드
> (Bind->Listen->Accept)->(Receive->Send)->Close
// 서버가 블라블라(BLA BLA)하는걸 듣고서 대답하고 닫기.
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using System.Net;
using System.Net.Sockets;
... ... ...
 
namespace TestSocketServer
{
    static void Main(string[] args)
    {
        int port = 8080;
        Socket serverSocket = null;
        Socket clientSocket = null;
        byte[] responseBytes = new byte[8192];
 
 
        //STEP.1 소켓 객체
        IPEndPoint endPoint = new IPEndPoint("172.0.0.1", port);
        serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 
        try{
            //STEP.2 (포트번호대로)수신 시작.
            serverSocket.Bind(endPoint);
            serverSocket.Listen(10);
 
 
            //STEP.3 새소켓
            clientSocket = serverSocket.Accept();
        } catch(SocketException except){
            Console.WriteLine(except.ErrorCode);
        } catch(ObjectDisposedException except){
            Console.WriteLine(except.ErrorCode);
        }
 
 
        int responseResult = -1;
        string responseString = null;
        while (!Console.KeyAvailable)
        {
            //STEP.4 새소켓으로 수신
            responseResult = clientSocket.Receive(responseBytes);
            responseString = Encoding.UTF8.GetString(responseBytes, 0, responseResult);
 
 
            //STEP.5 답신
            clientSocket.Send(responseBytes, 0, receiveResult, SocketFlags.None);
        }
 
        //STEP.6 소켓 
        clientSocket.Close();
        socket.Close();
    }
}
cs


3) 비동기 소켓 서버
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System.Net;
using System.Net.Sockets;
using System.Threading;
... ... ...
 
namespace TestSocketServer
{
    public static ManualResetEvent _threadEvent = new ManualResetEvent(false);
 
    static void Main(string[] args)
    {
        int port = 8080;
        Socket serverSocket = null;
 
 
        //STEP.1 소켓 객체
        IPEndPoint endPoint = new IPEndPoint("172.0.0.1", port);
        serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 
        try{
            //STEP.2 (포트번호대로)수신 시작.
            serverSocket.Bind(endPoint);
            serverSocket.Listen(10);
        } catch(SocketException except){
            Console.WriteLine(except.ErrorCode);
        } catch(ObjectDisposedException except){
            Console.WriteLine(except.ErrorCode);
        }
 
 
        try{
            while (true)
            {
                _threadEvent.Reset();
 
                //STEP.3 클라이언트 요청이 있을때마다 요청 수락
                serverSocket.BeginAccept(SocketCallback, serverSocket);//Accept.시작
 
                _threadEvent.WaitOne();// Wait until a connection is made before continuing.
            }
        } catch(Exception except){
            Console.WriteLine(except.ErrorCode);
        }
    }
 
    private static void SocketCallback(IAsyncResult argResultAsync)
    {
        Console.WriteLine("Accepted");
        Console.ReadLine();
 
        _threadEvent.Set();// Signal the main thread to continue.
 
        Socket listener = (Socket)argResultAsync.AsyncState;
        Socket clientSocket = listener.EndAccept(argResultAsync);//Accept.끝
 
        clientSocket.Close();
    }
}
cs




기타. 참조자료

1) 한국어
C# 프로그래밍 배우기 (Learn C# Programming)
TCP 클라이언트
비동기 TCP 서버

 
목차
1.
 스레딩 기본 제어
2.
 스레드풀






1. 스레딩 기본 제어


1) 생성 및 기본 사용.
> [#웹 컴파일]
> Thread형 오브젝트의 프로퍼티로 IsBackground를 설정후 start하는걸로 포그라운드/백그라운드 처리가능.

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System;
using System.Text.RegularExpressions;
using System.Threading;
 
namespace Rextester
{
    public class MyThreadClass
    {
        public static int SLEEP_MS = 10000;//10초.
        public static string TIME_FORM = "HH:mm:ss.fff";
        
        public void InstanceFunc(/*함수 인자 및 델레기이트 가능*/)
        {
            try{
                Console.WriteLine("[{0}] Thread {1}", DateTime.Now.ToString(TIME_FORM), Thread.CurrentThread.Name);
                Thread.Sleep(SLEEP_MS);
            }
            catch (ThreadInterruptedException) {
                Console.WriteLine("[{0}] ThreadInterruptedException, '{1}'", DateTime.Now.ToString(TIME_FORM), Thread.CurrentThread.Name);
            }
            catch (ThreadAbortException) {
                 Console.WriteLine("[{0}] ThreadAbortException, '{1}'", DateTime.Now.ToString(TIME_FORM), Thread.CurrentThread.Name);
            }
            
            Console.WriteLine("[{0}] FIN, {1}", DateTime.Now.ToString(TIME_FORM), Thread.CurrentThread.Name);
            /*
            Sleep이 호출되면 지정된 시간만큼 다른 스레드에게 리소스 양도.
            한 스레드가 다른 스레드에서 Thread.Sleep(정적 매소드)는 호출 불가.
            */
        }
        public static void StaticFunc(/*함수 인자 및 델레기이트 가능*/)
        {
            try{
                Console.WriteLine("[{0}] Thread {1}", DateTime.Now.ToString(TIME_FORM), Thread.CurrentThread.Name);
                Thread.Sleep(SLEEP_MS);
            }
            catch (ThreadInterruptedException) {
                Console.WriteLine("[{0}] ThreadInterruptedException, '{1}'", DateTime.Now.ToString(TIME_FORM), Thread.CurrentThread.Name);
            }
            catch (ThreadAbortException) {
                 Console.WriteLine("[{0}] ThreadAbortException, '{1}'", DateTime.Now.ToString(TIME_FORM), Thread.CurrentThread.Name);
            }
            
            Console.WriteLine("[{0}] FIN, {1}", DateTime.Now.ToString(TIME_FORM), Thread.CurrentThread.Name);
        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            MyThreadClass threadObj = new MyThreadClass();
            Thread threadForIns = null;
            Thread threadForStatic = null;
            threadForIns = new Thread(new ThreadStart(threadObj.InstanceFunc));            //함수 인자X
            //threadForIns = new Thread(new ThreadStart(threadObj.InstanceFunc(...)));
            threadForIns.Name = "InstanceFunc";
            threadForIns.Start();
 
            Console.WriteLine("[{0}] before Thread.Sleep", DateTime.Now.ToString(MyThreadClass.TIME_FORM));
            Thread.Sleep(MyThreadClass.SLEEP_MS / 5);
            Console.WriteLine("[{0}] before Interrupt", DateTime.Now.ToString(MyThreadClass.TIME_FORM));
            threadForIns.Interrupt();//wake쯤?
 
            //정적 함수이니 [클래스명.함수명]호출.
            threadForStatic = new Thread(new ThreadStart(MyThreadClass.StaticFunc));        //함수 인자X
            //threadForStatic = new new Thread(new ThreadStart(MyThreadClass.StaticFunc(...)));
            threadForStatic.Name = "StaticFunc";
            threadForStatic.Start();
            
            Console.WriteLine("[{0}] before Thread.Sleep", DateTime.Now.ToString(MyThreadClass.TIME_FORM));
            Thread.Sleep(MyThreadClass.SLEEP_MS / 5);
            Console.WriteLine("[{0}] before Abort", DateTime.Now.ToString(MyThreadClass.TIME_FORM));
            threadForStatic.Abort(); //스레드 제거
        }
    }
}
cs

> 실행결과

[15:44:59.345] before Thread.Sleep
[15:44:59.360] Thread InstanceFunc
[15:45:01.377] before Interrupt
[15:45:01.377] ThreadInterruptedException, 'InstanceFunc'
[15:45:01.377] FIN, InstanceFunc
[15:45:01.377] Thread StaticFunc
[15:45:01.377] before Thread.Sleep
[15:45:03.393] before Abort
[15:45:03.410] ThreadAbortException, 'StaticFunc'
 
 
2) 타이머
> System.Threading.Timer과 System.Timers.Timer 2가지가 존재.
[#예제, System.Timers.Timer] //Elapsed에 넣는 static함수는 Task도 허용.
[#예제, System.Threading.Timer] //TimerCallback을 이용한 델리게이트





2. 스레드 풀

1) 최소&최대
> 최대: 스레드 풀에 대기 시킬 작업수는 메모리가 관건이나,
CPU코어당-1개 이상의 스레드
                           1 스레드-최대 N개의 작업 스레드.
> ThreadPool.SetMaxThreads(), ThreadPool.SetMinThreads()로 작업 스레드 갯수 조절.


2) 세부 항목

> 스레드 및 스레딩 사용






기타. 참조자료

1) 한국어
C# 프로그래밍 배우기 (Learn C# Programming)
 
> 관리되는 스레딩 기본사항
> 스레드 및 스레딩 사용
> 스레딩 개체 및 기능
 




기타. 변경이력

일자
 변경이력
 2021-03-28  초안 작성.
목차
(1)
 기본 문법
(2)
 이벤트, 비동기





 

0. 필요한 파일

 

파일명
 예시경로
 VS 2019 [#다운로드]
> 16.3 이상
 (기본경로)
 .NET Core 3.0 [#다운로드]  (기본경로)

* 해당 포스트는 C# 8.0기반이며, VS 업데이트는 16.8.6입니다.
* 해당 포스트는 JAVA/파이썬 같은 다른 프로그래밍 언어를 알고 있는걸 전제로 생략되는 부분이 있습니다.





1. 문법

 

1) 상수류
> 상수 선언시 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 = {{1024512},{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가 권장.
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에도 동일한 네임스페이스 사용가능.
> 네임스페이스내 정의내 정의된 클래스를 가져다쓰려면
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처럼 인자를 입력.

④ 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(20212);
doFunction(2021228);
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
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를 사용하는걸까요?
 

 

* 비쥬얼 스튜디오 2017+윈도우10과 실물Mac 기준으로 진행하는 Xamarin(자마린) 설치입니다.


크로스 플랫폼: Xamarin(자마린) 앱 개발 (1)

크로스 플랫폼: Xamarin(자마린) 앱 개발 (2)

크로스 플랫폼: 자마린 설치 번외, VS2017






0. 필요한 파일


* NDK, android-sdk의 경우, 비쥬얼 스튜디오를 통한 설치로도 할수 있기때문에 해당 부분은생략이 가능합니다.


파일명

예시 경로

 Visual Studio Community

 [#for win]  [#for Mac]

 (설치 기본경로)

 Xamarin Forms Player [#] 
 Android용 에뮬레이터

 (해당사항 없음)
> 윈도우7&OS X, Xamarin Android Player

> 상위 OS, Visual Studio Emulator for Android

 JDK
 [#]
 C:\Java\jdk1.8.0_121
개발용 환경변수 설정(Path 설정) 참조.

 NDK

 [#]

 D:\dev_lib\android_ndk

> android-ndk-r17-windows-x86_64.zip
개발용 환경변수 설정(Path 설정) 참조.

 android-sdk D:\dev_lib\androidSDK
> sdk-tools-windows-3859397.zip
> (안드로이드: SDK 명령어 버전 참조)






1. 설치


1) 윈도우10

> 설치시 SDK를 별도로 경로잡아서 할지 아니면 VS 설치 옵션에서 한꺼번에 설치할지의 차이정도라 이 부분은 별도로 설명치 않겠습니다.



2) Mac

만약 설치가 잘못 됐을경우, 삭제명령어는 아래의 링크중 하나를 참조하면 됩니다.

Mac용 Visual Studio 제거 | Microsoft Docs

Xamarin 제거 - Xamarin | Microsoft Docs






2. 환경설정


1) 경로지정



2) SDK 관리


① 플랫폼

> 최저/최고 사양으로 사용할 버전

② 도구

> Android SDK Tools: 최신버전 확인 혹은 업데이트

> Android SDK Build Tools: 최신버전 확인 혹은 업데이트

> 추가: Android Support Repository, Google Repository 최신버전 확인 혹은 업데이트







3. 빌드확인


* 기본적인 설정이 제대로 된건지 확인하기 위해 자마린 공식페이지에서 제공하는 샘플 프로젝트로 빌드해봅니다.

[#Xamarin.Forms Samples]


1) 안드로이드

시작 프로젝트로 지정후 빌드를 해도

만약 이상태에서 빌드가 안 되면 NuGet패키지를 업데이트로 해결이 가능합니다.



2) iOS

* 다시 말씀드리지만, 가상머신+Mac으로 하는 원격빌드가 아닌 실물 기기에서 진행했습니다.

* 애플 개발자 계정&기존에 있던 ad hoc 프로비져닝 파일로 빌드 테스트를 했습니다.


① Info.plist

> 프로비져닝은 오토로 합니다.

  apple ID를 등록하는 버튼이 생성되면 메뉴내에서 애플 개발자계정을 추가합니다. 캡쳐에도 있다시피 별도로 연결된 팀이 없어도 빌드&deploy는 가능했습니다.






기타. 참조자료


DocsXamarinXamarin.iOS배포 및 테스트

[자마린 시리즈] iOS 디바이스 무료 프로비저닝 방법

iOS 인증서 및 프로비저닝 프로파일 만들기 – Nova Woo – Medium


Even Easier iOS App Provisioning in Visual Studio for Mac  | Xamarin Blog


How to Create a Free iOS Development Provisioning Profile | LiveCode


No installed provisioning profiles match the installed iOS signing keys 관련

Xamarin 환경 확인(mdsn)

Publishing to the App Store - Xamarin | Microsoft Docs






기타. 변경이력


일자

변경이력

2018-05-11

 초안


* 만약기본 프로젝트 생성 직후 빌드시, error: duplicate class: src.droid.R등으로 빌드 실패가 뜰 경우
솔루션을 정리하거나 하드상에 완전히 삭제후 다시 시도하다보면 정상적으로 빌드가 됩니다.

* 개인 프로젝트와 병행한 포스팅이라 폴더명등에 모자이크 처리가 존재합니다.


크로스 플랫폼: Xamarin(자마린) 앱 개발 (1)

크로스 플랫폼: Xamarin(자마린) 앱 개발 (2)

크로스 플랫폼: 자마린 설치 번외, VS2017






1. 프로젝트 구성


* Xamarin(자마린) 앱 개발 (1)내 '솔루션 및 프로젝트 생성'에서 이어지는 내용입니다.


1) 공유 데이터 서비스 코드 작성

프로젝트명(이식가능)이 PCL 프로젝트, 플랫폼 공용코드를 작업할 프로젝트입니다.

해당 프로젝트에 폴더등을 추가하고, 또한 공용 클래스를 작성합니다.

(예. SQL등등)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace SOLUTION_NAME
{
    class USR_CLASS
    {
        public string OPT { get; set; }
        ... ... ...
 
        public USR_CLASS()
        {
            //Because labels bind to these values, set them to an empty string to
            //ensure that the label appears on all platforms by default.
            this.OPT = " ";
            ... ... ...
        }
    }
}
cs



2) UI 코드 작성 시작

안드로이드 프로젝트에서 다음과 같은 항목을 추가합니다.






2. 프로젝트 설정


1) 어플 정보 변경

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
 
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
 
namespace proj_name.Droid
{
    [Activity(Label = "앱 이름", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
 
            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App());// 공용 프로젝트에 있는 클래스
        }
    }
}
cs

> Label: 출력되는 앱 이름

> Icon

   Resources/drawable등에서 icon.png파일을 교체합니다.

   JAVA&이클립스와 달리 아이콘 파일명이 시스템 상으로 고정된듯합니다.

* 라벨과 아이콘은 [안드로이드용 프로젝트 우클릭>AndroidManifest]에서도 지정이 가능합니다. 간결성을 위해 스크립트가 아닌 AndroidManifest에서 하는방법도 있습니다.

> 패키지 네임

   안드로이드용 프로젝트 우클릭>AndroidManifest



2) 빌드시 유의사항

> 안드로이드용 빌드일 경우, 안드로이드용 프로젝트를 시작 프로젝트로 설정해야합니다.

Application Package Sizes - Xamarin

> Publishing an Application - Xamarin

Linking on Android - Xamarin






3. UI 및 레이아웃 관련


1) 입력 제어

Detect a Touch - Xamarin



2) UI구성

ListView Example in Xamarin.Android (BaseAdapter)

Part 2 - Populating a ListView With Data - Xamarin

Part 3 - Customizing a ListView's Appearance - Xamarin

커스텀 다이얼로그(for xamarin android)

axml, java관련 에러 처리



3) 로컬 저장

SQLite.NET

Create a Database with SQLiteNET

Working with a Local Database

An Introduction to Xamarin.Forms and SQLite

> 샘플 프로젝트: TaskyPortable

> PCL기준입니다. Shared Projects방식은 Working with a Local Database에서 'Using SQLite with Shared Projects'항목을 보시면 됩니다.


Android.Net: Xamarin Android - Application Overview- Using the application class for global variables


sqlite-net-pcl 패키지를 PCL&플랫폼별 프로젝트에 설치합니다. 유사검색결과가 많은데, 작성자와 신고 페이지등등 다음의 정보를 확인해야 합니다.

작성자: Frank A. Krueger

NuGet 링크: https://www.nuget.org/packages/sqlite-net-pcl/xxx/xxx  (xxx부분 생략 가능)


만약, 안드로이드로만 개발하신다면 SharedPreferences로도 가능합니다. [#링크]






기타. openTK


1) 라이브러리

① 연결

에러: OpenTK 설치실패


② 버전 및 API대응

OpenGL ES 1.0 and 1.1 - This API specification is supported by Android 1.0 and higher.

OpenGL ES 2.0 - This API specification is supported by Android 2.2 (API level 8) and higher.

OpenGL ES 3.0 - This API specification is supported by Android 4.3 (API level 18) and higher.

OpenGL ES 3.1 - This API specification is supported by Android 5.0 (API level 21) and higher. 



2) 기본구조

OpenTK.Graphics (OpenGL and ES)

Frame Buffer Objects (FBO)

> Every OpenGL application has at least one framebuffer.

> FBO allows 2 Renderbuffers



3) 2D

2D Texture differences

Drawing

Drawing Optimizations

OpenTK: Simple Movable Sprite



4) 3D

GL Triangle  [#3.0] [#2.0] [#1.0]


5) 오디오

OpenTK.Audio (OpenAL)






기타. 참조자료


Samples - Xamarin

GitHub - xamarin/urho-samples: Samples for the Urho bindings

Stripping unused Java code (from components) - Xamarin Forums


최초가 되거나 최고가 되어라 :: 03. Xamarin(자마린)을 이용하여 Android/Windows/iOS에 Hello World 출력하기


Building Cross Platform Applications - Xamarin

Part 1. Getting Started with XAML - Xamarin

Creating Mobile Apps with Xamarin.Forms Book First Edition - Xamarin

Part 3 - Setting Up A Xamarin Cross Platform Solution - Xamarin

Part 1 - Designer Basics - Xamarin






기타. 변경이력


일자

변경이력

2016-12-29

 초안






1. 개요


1) 닷넷 프레임워크란?

> 닷넷 프레임워크(.NET Framework) 공용 언어 런타임(CLR, Common Language Runtime)과 닷넷 프레임워크 클래스 라이브러리로 구성되어 있다.


 공용 언어 런타임

(CLR, Common Language Runtime)

 실행 중인 응용 프로그램을 처리하는 실행 엔진 / which is the execution engine that handles running applications

 메모리, 스레드 실행, 코드 실행, 코드 안전성 확인, 컴파일 및 기타 시스템 서비스를 관리

 CTS(공용 형식 시스템)라고 하는 엄격한 형식 및 코드 확인 인프라를 구현하여 코드 견고성을 유지

 Side-by-Side 실행. 동일한 컴퓨터에 여러 버전의 CLR이 존재하도록 허용함으로써 버전 충돌을 해결. 즉, 여러 버전의 응용 프로그램이 공존할 수 있으며 응용 프로그램이 해당 응용 프로그램을 빌드한 닷넷 버전에서 실행될수 있다.

 닷넷 프레임워크 클래스 라이브러리

 공용 언어 런타임과 강력하게 통합된 다시 사용할 수 있는 형식의 컬렉션

 / a collection of reusable types that tightly integrate with the common language runtime.



2) 구조관련

① 공통언어 기반(CLI)

> 닷넷 프레임워크의 가장 중요한 콤포넌트는 공통 언어 기반(Common Language Infrastructure)이다. 다른 말로 CLI라고 한다. CLI를 둔 목적은 애플리케이션의 개발과 실행 시 언어에 종속적이지 않은 플랫폼을 제공하기 위해서이다. 예외 처리, 가비지 콜렉션, 보안, 호환 등을 위한 소프트웨어 콤포넌트를 포함한다. 마이크로소프트가 구현한 CLI를 일컬어, 공통 언어 런타임(Common Language Runtime, CLR)이라고 한다.[각주:1]

Overview of the Common Language Infrastructure.svg
By Jarkko Piiroinen - Own work, Public Domain, https://commons.wikimedia.org/w/index.php?curid=3602584


②어셈블리

> 어셈블리는 파일 1개이상으로 구성. 파일들중 1개는 매니페스트를 꼭 포함해야 한다.


③베이스 클래스 라이브러리(BCL)

> 닷넷 프레임워크를 사용하는 모든 언어가 사용할수 있는 클래스들의 라이브러리

> 파일 읽기/쓰기, 그래픽 렌더링, 데이터베이스 조작, XML 조작 등과 같은 공통된 기능 제공


* 메모

> 위키백과 언어별로 제각각이고 msdn페이지에 별도로 언급된게 없어 ③까지 명시했습니다.






2. 버전


1) 버전별 차이점

DotNet.svg
By Soumyasch - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=2953328



2) 주요 변경점

버전

주요 변경점

1.0

 ASP.NET의 모바일 기능 추가

1.1

 IPv6 지원

2.0

 64 비트 (x64 및 IA-64) 대응

3.0

 XP 이전 OS에서 작동불가

3.5

 ASP.NET AJAX 의 대응

4.0

 Visual Studio 2010부터 지원

 병렬 프로그래밍 지원

4.5

 Visual Studio 2012부터 지원

 닷넷 4.5는 닷넷 4와 거의 호환가능

 * 마이너 버전으로 4.5.1 및 4.5.2도 있지만, 추가 패키지 (Developer Pack 또는 Targeting Pack)등으로 Visual Studio 2012에서 개발할수도 있음.

4.6

 Visual Studio 2015부터 지원
 ASP.NET 5 대응
 오픈소스화






기타. 참조자료


.NET Framework - Wikipedia

> 영문판

> 일어판


msdn

.NET Framework 시작

.NET Framework의 개요


[HOONS] (1) 닷넷 프레임워크 3.0의 소개 - HOONS닷넷

namespace:: hyunjin :: [C# 기초문법] 1. .NET Framework (닷넷 프레임 워크)






기타. 변경이력


일자

변경이력

2016-08-21

 초안


  1. 닷넷 프레임워크, 공통 언어 기반 https://ko.wikipedia.org/wiki/%EB%8B%B7%EB%84%B7_%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC#.EA.B3.B5.ED.86.B5_.EC.96.B8.EC.96.B4_.EA.B8.B0.EB.B0.98 [본문으로]

다음과 같은 상황에 활용해볼만한 예시입니다.

> 홈버튼/파워버튼 사용시 앱종료 같은 추가 동작을 구현

> 슬립모드->액티비티 실행 & (화면on상태에서)액티비티 실행같은 변수작용





액티비티 라이프 사이클에 포함되는 함수들에 로그를 찍어보면 아래와 같은 실행순서가 됩니다.


 슬립모드->액티비 실행

 (화면이 켜진상태에서)액티비티 실행

OnCreate

OnStart

OnResume

OnPause

OnStop//액티비티 출력처리 완료.


(홈버튼)

OnRestart

OnStart


OnResume

OnPause

OnStop

OnCreate

OnStart

OnResume//액티비티 출력처리 완료.








(홈버튼)

OnPause

OnStop

(OnDestroy)

로그상 OnRestart, OnStart등에서 추가적으로 플래그값을 조절하면 좀더 다양한 제어가 가능하지 않을까 싶습니다.


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
    ... ... ...
    ... ... ...
    ... ... ...
    protected override void OnUserLeaveHint()
     {
         //홈버튼에 따른 플래그값 혹은 제어
         base.OnUserLeaveHint();
     }
 
    public override bool OnKeyDown(Keycode keyCode, KeyEvent e)
    {
        if (keyCode == Keycode.Back)
        {
            this.Finish();
        }
        else if (keyCode == Keycode.Sleep)
        {
            this.Finish();
        }
        else if (keyCode == Keycode.Power)
        {
            this.Finish();
        }
        //Console.WriteLine("OnKeyDown. " + keyCode.ToString());
 
        return base.OnKeyDown(keyCode, e);
    }
    ... ... ...
    ... ... ...
    ... ... ...
}
cs







1
2
3
4
5
6
7
8
9
using System;
using Android.Util;
 
... ... ...
Console.WriteLine("[Console.WriteLine]");
Log.Debug("Log.Debug""000");
Log.Info("Log.Info""111");
Log.Warn("Log.Warn""222");
Log.Error("Log.Error""333");
cs




06-08 09:13:02.755 I/mono-stdout(22963): [Console.WriteLine]

[Console.WriteLine]

06-08 09:13:02.765 D/Log.Debug(22963): 000

06-08 09:13:02.765 I/Log.Info(22963): 111

06-08 09:13:02.765 W/Log.Warn(22963): 222

06-08 09:13:02.775 E/Log.Error(22963): 333

  1. Favicon of http://blog.naver.com/kdzdsyygijfs/220730461518?75773 BlogIcon 1466126642 2016.06.17 10:24

    좋은 정보 잘보고 갑니다

  2. Favicon of http://blog.naver.com/shegirl1003/220735869071?79127 BlogIcon 1467589853 2016.07.04 08:50

    알찬 정보 좋네요~

* 개인 프로젝트와 병행한 포스팅이라 폴더명등에 모자이크 처리가 존재합니다.

* 비쥬얼 스튜디오 2015&윈도우7 기준입니다.


크로스 플랫폼: Xamarin(자마린) 앱 개발 (1)

크로스 플랫폼: Xamarin(자마린) 앱 개발 (2)

크로스 플랫폼: 자마린 설치 번외, VS2017






0. 필요한 파일


파일명

예시 경로

 Visual Studio Community [#]

 (설치 기본경로)

 ADT (NDK 플러그인) (해당사항 없음)
 Android용 에뮬레이터

 (해당사항 없음)
> 윈도우7&OS X, Xamarin Android Player

> 상위 OS, Visual Studio Emulator for Android

 JDK C:\Java\jdk1.8.0_60
개발용 환경변수 설정(Path 설정) 참조.

 android-ndk-r11c-windows-x86.zip

 [#]

 C:\android-ndk
개발용 환경변수 설정(Path 설정) 참조.

 android-sdk (안드로이드: SDK 명령어 버전 참조)


* 기존에 VS가 설치되었고, SDK등이 이미 세팅된 상황이면 자마린만 설치하는것도 괜찮습니다.

* VS 설치시 자동으로 NDK와 JDK등도 설치됩니다.

C:\Program Files\Java\(...중략...)

C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r10e

C:\Program Files\Microsoft Visual Studio 14.0\Apps\apache-ant-1.9.3

가 처리되긴해도 버전관리가 편하게 별도로 다운받아서 사용했습니다.


* SDK경로명에 가급적 '-'를 피하는걸 권장합니다.

RebelBox.com – Visual Studio – Cross platform mobile development with C++.







1. 추가 세팅


도구>옵션






1. 기본 세팅


1) 솔루션 및 프로젝트 생성

로컬이 윈도우7이라 발생한거 같습니다.


여기까지 해도 괜찮겠지만

개인적으로 src하위 폴더와 솔루션내 하위 프로젝트명들 식별성을 좀더 주고 싶어서 추가편집을 했습니다.

> (VS)솔루션명 변경

> 디렉토리상 폴더명 변경

> 솔루션 sln파일 편집

1
2
3
4
5
6
7
8
9
10
11
12
//pcl_sample\pcl_sample.sln
 
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{... ... ...}") = "proj_name.Droid", "src\proj_name.Droid\proj_name.Droid.csproj", "{... ... ...}"
EndProject
Project("{... ... ...}") = "proj_name.iOS", "src\proj_name.iOS\proj_name.iOS.csproj", "{... ... ...}"
EndProject
Project("{... ... ...}") = "proj_name", "src\proj_name\proj_name.csproj", "{... ... ...}"
EndProject
cs



2) NuGet 패키지 관리

도구 > NuGet 패키지 관리자 > 솔루션용 NuGet 패키지 관리

용도에 맞는 패키지를 선택해서
PCL 및 플랫폼별 프로젝트에 설치해주면 됩니다.






2. msdn


Xamarin 환경 확인

Visual Studio에서 Xamarin.Forms를 사용한 앱 빌드 기본 사항 알아보기






기타. 참조자료


Setting Up Xamarin Development Environment In Windows And iOS


Visual Studio 및 Xamarin(MSDN)

Visual Studio에서 Xamarin을 사용하여 네이티브 UI로 앱 빌드


최초가 되거나 최고가 되어라 :: 01. 크로스플랫폼 개발(Android/iOS/Windows)을 위한 Xamarin(자마린) 설치하기

최초가 되거나 최고가 되어라 :: 02. Xamarin(자마린) Forms 개발 환경 구축하기


Xamarin.Forms Quickstart - Xamarin

Xamarin.Forms에 대 한 라이브 플레이어 - Xamarin | Microsoft Docs






기타. 변경이력


일자

변경이력

2016-05-17

 초안.

2016-08-07

 1) 솔루션 및 프로젝트 생성
 내용 개편

2017-06-20

 2. msdn추가

2018-04-16

 설치관련 개정






0. 필요한 파일 & 예시경로


설치 및 예시경로

 SharpDevelop
 [#다운로드]

 C:\Program Files\SharpDevelop\(버전명)

 .NET Framework

 (기본경로값)

-> 샤프 디벨롭3.2부터는 Frameworks 2.0이상 필요




1. 데이터 타입&enum


1) 리터럴 데이터

 변수에 입력하는 값에 접미어 표시(Suffix)가 없을경우, 다음의 5가지 데이터 타입을 기본으로 할당한다.

 int

 double

 char

 string

 bool


그외 리터럴 데이터 타

-> char과 string 다른 언어하고 동일하게 ''/""로 구분된다.

 long

 unit

 ulong

 float

 double

 decimal

 long var = 2014L;

 unit var = 2014U;

 ulong var = 2014UL;

 float var = 2014F;

 double var = 2014.12D;

 or double var = 2014.12;

 decimal var = 2014.12M;



2) Nullable Type

-> C# 2.0부터 Value Type 변수에 null을 가질수 있다.

-> [??]연산자와 연관성이 있음.

-> 예.  int? a;



3) 배열

-> C# 배열도 Zero-based Array라 첫번째 배열원소 인덱스값이 0이다.

1차원 배열

 int[] idx1 = new Int[5];

 int[] idx2 = {11, 22, 33, 44, 55};

 2차원 배열

 int[,] idx2 = { {21, 22, 23, 24, 25},

                     {31, 32, 33, 34, 35} };

 int[][] idx1 = new int[5][];   //가변배열(Jagged Arr.)

 idx1[] = new int[4];             //배열마다 새로 할당가능.

 idx1[] = new int[2] {1, 2,};

 idx1[] = new int[5];

 3차원 배열

 int[,,] idx;



4) 열거형

C# enum (열거형)



5) 기타

-> 문자열: Immutable이라, 한번 지정된 문자열은 새로 지정하더라도 내부적으로 전혀 다른 메모리를 갖는 객체가 된다고 한다.

-> 전역은 선언시 초기화 안 해도 기본값 자동 / 로컬은 그렇게 했다가 에러




2. 기본 제어


* if, for, switch-case문은 다른 언어와 사용법이 동일해서 생략


1) foreach 반복문

-> 배열/컬렉션뿐 아니라, 다차원 배열에도 유용하다고 한다.

for문

foreach문

int[,] idxArr = { {21, 22, 23, 24, 25},

                       {31, 32, 33, 34, 35} };


for(int line = 0; line < idxArr.GetLength(0); line++)

{

   for(int row = 0; row < idxArr.GetLength(1); row++)

   {

      ... ...

   }

}

int[,] idxArr = { {21, 22, 23, 24, 25},

                       {31, 32, 33, 34, 35} };


foreach (int tmp in idxArr)
{
   ... ...
}






2) 예외처리, try-catch

try
{
   ...
}
catch (Exception ex)
{
   ...

   throw; //throw문 뒤에 Exception객체가 있을경우: 기존 혹은 새로운 객체를 쓰게 함.

             //throw문 뒤에 아무것도 없을경우: 발생된 에러를 디버깅하기 좋음.

}
catch (... ex)
{
   ...
}
finally
{//중간에 에러가 나도 반드시 실행되는 구간
   ...



3) yield
C# yield


4) 전처리기

1
2
3
4
5
6
7
8
9
10
#define DEBUG//심벌
//#define RELEASE
 
#if DEBUG
    ... ... ...
#else
    ... ... ...
    //심벌 RELEASE를 주석해제하고, 심벌 DEBUG를 주석처리시 실행.
#endif
    ... ... ...
cs


기타

#region과 #endregion

> #pragma

자세히 읽기






3. 함수


1) 종류

* 규칙상 5가지 방식으로 구별할 수 있다.

 Pass by Value

 함수인자에 변수를 넣어주는 일반적인 방식이다.

 키워드, ref

 함수 인자에 ref가 붙으면, 함수내에서 변경된 변수값이 함수 밖에서도 유효.

ref가 붙는 변수는 사용전 초기화가 되어야 한다.

 Named 파라미터

 4.0부터 위치 상관없이 파라미터명으로 파라미터 전달가능.

 Optional 파라미터

 4.0부터 가능한 방식. (액션스크립트 3.0에도 쓰임. 미묘하게 다형성이 연상됨.)

 함수인자에서 변수에 기본값을 지정해두면, 함수호출시 해당 인자를 생략해도 된다.

 단, Optional 파라미터에 해당되는 인자가 맨뒤로 배치되야 한다.


ex. void calFunc(int val1, int val2, int result = 0)

{

   ... ... ...

}

... ... ...

calFunc(2014, 12);

calFunc(2015, 12, 21);

 키워드, params

 함수인자에 가변배열 사용가능하게 함.


 ex.

void calFunc(params int[] val)

{

   ... ... ...

}



2) Static 메서드

-> 메서드 내부에서 클래스 인스턴스 객체 멤버를 참조해서는 안된다. (반환타입 있는 메소드로만 사용?)



3) 익명함수

익명 함수(C# 프로그래밍 가이드)



4) 확장 매소드?
-> C# 3.0부터 지원.
-> 다른 클래스의 인스턴스 매소드처럼 사용가능한 static 매소드






4. 클래스


1) 상속

public class Child : Parent

public class Child : MyInterface1, MyInterface2        //인터페이스 선언시, 접근제한자X. 구현은 재정의 해주는 그거임
public class Child : Parent, MyInterface1, MyInterface2


btn.Click += new EventHandler(btn_Click);

partial 키워드는 class, struct, interface 키워드 바로 앞에 위치해야    //Abstract랑 유사?

1
2
3
4
5
6
7
8
9
10
11
public class Parent
{
    public int _mem1 = 0;
    protected int _mem2 = 0;
 
    public virtual void Func1()
    {
        ... ... ...
    }
    ... ... ...
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Child : Parent
{
    //public int _mem1 = 0;
    //protected int _mem2 = 0;
 
    //부모함수 재정의
    public override void Func1()
    {
        base.Func1();//부모함수의 동작도 사용.
        ... ... ...
    }
    ... ... ...
}
cs



2) 인덱서

-> 객체가 배열이 아닌데도 배열처럼 클래스내 특정 멤버변수에 접근 가능.

//인덱서
MyClass cls = new MyClass();
      cls[1] = 1024;

class DataObj

{

   ... ...

   public int this[int idx]

   {

      get

      {

      }

      set

      {

      }

   }

}

class



3) is & as

-> as 연산자: 객체를 지정된 클래스 타입으로 변환하는데 사용된다. 만약 변환이 성공하면 해당 클래스 타입으로 캐스팅하고, 변환이 실패하면 null 을 리턴
EX.
    MyBase a = obj as MyBase;    //as연산자로 캐스팅
    MyBase b = (MyBase) obj;     //Implicit Casting. 암묵적 캐스팅. 변환이 실패하면 Exception을 발생
-> is 연산자: 객체가 특정 클래스 타입이나 인터페이스를 갖고 있는지 확인하는데 사용



4) 기타
상속 및 파생 클래스(C# 및 Java)





5. 네임스페이스


C# 네임스페이스 참조
-> C++쪽하고 큰차이는 없다.





6. 고급요소


1) delegate
함수 포인터랑 비슷?

특이하게 함수인자는 int만 가능.



2) Generics
> C++의 템플릿과 비슷
> 클래스, 인터페이스, 메서드 등에 <T> 같은 타입 파라미터를 붙여 사용.
> 어떻게 보면 오버로드(다형성)랑 연관있는 타입
> 또한 using System.Collections.Generic 네임스페이스에 있는 모든 자료구조 관련 클래스가 Generics타입.


3) Property(프로퍼티)
> 필드와 매소드 특징을 모두 가지고 있어서, get/set접근자로 값을 쓰거나 읽어올수 있다.
 여기서 set접근자는 반환타입이 void인 매서드와 유사.


4) 그외
await: Task와 같은 awaitable 클래스 객체가 완료되기를 기다림.






기타.







기타. 변경이력


일자

변경이력

2015-12-21

 초안

2016-01-20

 상속 내용 보완 및 보충

> 재정의

> base 예약어

2016-08-10

 6. 고급요소 보완 및 보충



+ Recent posts