달력

5

« 2024/5 »

  • 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
2016. 5. 10. 21:17

연산자 2 프로그래밍/C#2016. 5. 10. 21:17

https://msdn.microsoft.com/ko-kr/library/6a71f45d.aspx


+ 연산자


class Plus { static void Main() { Console.WriteLine(+5); // 단항 플러스(unary plus) Console.WriteLine(5 + 5); // 더하기(addition) Console.WriteLine(5 + .5); // 더하기(addition) Console.WriteLine("5" + "5"); // 문자열 연결(string concatenation) Console.WriteLine(5.0 + "5"); // 문자열 연결(string concatenation) // double 에서 문자열로 자동 변환된다. } } /* Output: 5 10 5.5 55 55 */





- 연산자


class MinusLinus
{
    static void Main()
    {
        int a = 5;
        Console.WriteLine(-a);
        Console.WriteLine(a - 1);
        Console.WriteLine(a - .5);
    }
}
/*
Output:
-5
4
4.5
*/





! 연산자


    - 논리 부정 연산자 (!)는 피연산자를 부정하는 단항 연산자입니다.

    - bool 형식으로 정의 되어 있고 false 인 경우에만 true를 반환합니다.

class MainClass4
{
    static void Main()
    {
        Console.WriteLine(!true);
        Console.WriteLine(!false);
    }
}
/*
Output:
False
True
*/





~ 연산자

    - 비트 보수 연산(bitwise complement operation)을 수행하여 각 비트를 반전시킵니다.

    - 비트 보수 연산자는 int, uint, long, ulong 형에 대해 미리 정의 되어 있습니다.

참고

~ 기호는 소멸자를 선언하는 데에도 사용됩니다.


class BWC
{
    static void Main()
    {
        int[] values = { 0, 0x111, 0xfffff, 0x8888, 0x22000022 };
        foreach (int v in values)
        {
            Console.WriteLine("~0x{0:x8} = 0x{1:x8}", v, ~v);
        }
    }
}
/*
Output:
~0x00000000 = 0xffffffff
~0x00000111 = 0xfffffeee
~0x000fffff = 0xfff00000
~0x00008888 = 0xffff7777
~0x22000022 = 0xddffffdd
*/




++ 연산자


    - 증가 연산자(increment operator)는 피연산자를 1씩 증가시킵니다.

    - 첫째 형태는 전위 증가 연산(prefix increment operation)입니다.

    - 둘째 형태는 후위 증가 연산(postfix increment operation)입니다.

class MainClass
{
    static void Main()
    {
        double x;
        x = 1.5;
        Console.WriteLine(++x);
        x = 1.5;
        Console.WriteLine(x++);
        Console.WriteLine(x);
    }
}
/*
Output
2.5
1.5
2.5
*/





-- 연산자


    - 감소 연산자(decrement operator)는 피연산자를 1씩 감소시킵니다.

    - 첫째 형태는 전위 감소 연산(prefix decrement operation)입니다.

    - 둘째 형태는 후위 감소 연산(postfix decrement operation)입니다.

class MainClass5
{
    static void Main()
    {
        double x;
        x = 1.5;
        Console.WriteLine(--x);
        x = 1.5;
        Console.WriteLine(x--);
        Console.WriteLine(x);
    }
}
/*
Output:
0.5
1.5
0.5
*/





() 연산자


    - 형식 캐스팅 (type casting)

    - 연산의 순서를 지정하기 위해 사용합니다.


1. 캐스팅 또는 형식 변환을 지정합니다.

double x = 1234.7; int a; a = (int)x; // double 을 int 로 변환


2. 메서드 또는 대리자 호출(Invoke methods or delegates)

TestMethod();


3. 캐스트는 명시적으로(explicitly) 한 형식에서 다른 형식의 변환 연산자를 호출합니다.

4. 해당하는 변환 연산자가 정의되어 있지 않다면 캐스트는 실패합니다.

5. 변환 연산자 정의에 대해서는 explicit 및 implicit를 참조하십시오.

6. () 연산자는 오버로드되지 않습니다.

7. 캐스트 식을 사용하면 구문이 모호해질 수 있습니다.

8. 예를 들면 (x)-y 식을 -y 를 x 형식으로 변환한다고 해석할 수 있고,

9. 또는 x - y 의 가감식으로 해석될 수 있습니다.





Await


    - 비동기 메서드(asynchronous method)의 작업에 적용됩니다.

    - 대기 중인 작업이 완료 될때까지 메서드의 실행을 중단(suspend)시킵니다.

    - 작업은 진행 중(ongoing)인 작업을 나타냅니다.

    - await가 사용되는 비동기 메서드는 async 키워드로 수정해야 합니다.

    - async 한정자를 사용해서 정의되고 일반적으로 하나 이상의 await 식을 포함하는 그러한 메소드는 비동기 메서드라고 합니다.


1. 일반적으로 await 연산자가 적용되는 작업은 작업 기반 비동기 패턴을 구현하는 메서드를 호출하여 얻은 반환값입니다.

2. 예는 Task 또는 Task<TResult> 형식의 값이 포함됩니다.

3. 다음 코드에서 HttpClient 메서드 GetByteArrayAsync는 Task<byte[]>, getContentsTask를 반환합니다.

4. 작업은 작업이 완료될 때 실제 바이트 배열을 생성하기 위한 약속입니다.

5. await 연산자는 getContentsTask에 적용되어 getContentsTask가 완료될 때까지 SumPageSizeAsync의 실행을 일시 중단합니다.

6. 동시에(In the meantime) 컨트롤은 SumPageSizesAsync 호출자에게 반환됩니다.

7. getContentsTask가 완료되면 await 식이 바이트 배열로 계산됩니다.


private async Task SumPageSizesAsync() { // 데스크탑 앱에서 HttpClient 형을 사용하려면 using 문을 사용해서 System.Net.Http 네임스페이스 참조를 추가해야 합니다. HttpClient client = new HttpClient(); // . . . Task<byte[]> getContentsTask = client.GetByteArrayAsync(url); byte[] urlContents = await getContentsTask; // 똑같이 한 줄의 코드로 작성할 수 있습니다. //byte[] urlContents = await client.GetByteArrayAsync(url); // . . . }


8. 위의 예제와 같이 await가 Task<TResult>를 반환하는 메서드 호출의 결과는 TResult 입니다.
9. await가 Task를 반환하는 메서드 호출의 결과는 void입니다.

// Task<TResult>를 반환하는 메서드와 사용된 키워드 await TResult result = await AsyncMethodThatReturnsTaskTResult(); // Task를 반환하는 메서드와 사용된 키워드 await await AsyncMethodThatReturnsTask();


10. await 식은 해당 식이 실행되고 있는 스레드를 차단하지 않습니다.
11. 대신 컴파일러에게 대기 중인 작업의 연속된 작업으로 비동기 메서드의 나머지 부분을 등록하도록 합니다.
12. 그런 다음 컨트롤이 비동기 메서드의 호출자에게 반환됩니다.
13. 작업이 완료되면 해당 연속 작업(continuation)이 호출되고 중단된 비동기 메서드의 실행이 다시 시작(resume)됩니다.
14. await 식은 바로 바깥쪽 메서드 또는 람다 식 또는 async 한정자로 표시된 무명 메서드 본문에서만 발생할 수 있습니다.
15. await 용어는 해당 컨텍스트에서만 키워드 역할을 합니다.
16. 다른 컨텍스트에서는 식별자로 해석됩니다.
17. 메서드, 또는 람다 식, 또는무명 메서드 내에서 await 식은 동기 함수의 본문, 커리식, lock 문 블록, 또는 unsafe 컨텍스트에서 발생할 수 없습니다.

18. 대부분의 비동기 메서드는 Task 또는 Task<TResult>를 반환합니다.

19. 반환된 작업의 속성은 작업의 완료 여부, 비동기 메서드가 예외를 발생시켰거나, 취소되었는지의 여부, 최종 결과 등 해당 상태와 기록을에 대한 정보를 전달합니다.

20. await 연산자는 해당 속성에 액세스합니다.

21. 예외를 발생시키는 작업 반환 비동기 메서드를 기다릴 경우 await 연산자는 예외를 다시 던집니다.

22. 취소된 작업 반환 비동기 메서드를 기다릴 경우 await 연산자는 OperationCanceledException을 다시 throw합니다.

23. 오류가 발생한 상태의 단일 작업에는 여러 예외가 반영될 수 있습니다.

24. 예를 들어 작업은 Task.WhenAll 호출의 결과일 수 있습니다.

25. 이러한 작업을 기다릴 경우 await 작업에서 예외중 하나만 다시 던집니다.

26. 그러나 어떤 예외가 다시 던져질 지는 예측할 수 없습니다.

27. 비동기 메서드의 오류 처리에 대한 예제는 see try-catch를 잠조하세요.

예제

28. 다음 윈도우 폼 예제는 비동기 메서드 WaitAsynchronouslyasync에서의 await 사용을 보여줍니다.

29. 해당 메서드의 동작을 WaitAsynchronously의 동작과 대조(contrast)합니다.

30. await 연산자가 작업에 적용되지 않으면 본문에서 Thread.Sleep을 호출하더라도 WaitSynchronously 는 동기적(Synchronously)으로 실행됩니다.


private async void button1_Click(object sender, EventArgs e) { // 비동기적으로 실행하는 메서드 호출 string result = await WaitAsynchronouslyAsync(); // 다음은 동기적으로 실행하는 메서드 호출 //string result = await WaitSynchronously (); // 결과 표시 textBox1.Text += result; } // 다음 메서드는 비동기적으로 실행된다. // UI 스레드는 delay 동안에 차단되지 않는다. // Task.Delay가 실행되는 동안에 Form1 창을 이동하거나 리사이즈 할 수 있다. public async Task<string> WaitAsynchronouslyAsync() { await Task.Delay(10000); return "Finished"; } // 다음 메서드는 async의 사용에도 불구하고 동기적으로 실행된다. // Thread.Sleep이 실행되는 동안에 Form1 창을 이동하거나 리사이즈할 수 없다. // 왜냐하면 UI thread가 차단되었기 때문이다. public async Task<string> WaitSynchronously() { // System.Threading 에 대해서 using 문을 추가하라. Thread.Sleep(10000); return "Finished"; }





& 연산자

    - & 연산자는 단항(unary) 또는 이항(binary) 연산자로 사용할 수 있습니다.


1. 단항 & 연산자는 피연산자(operand)의 주소를 반환합니다.(unsafe 컨텍스트 필요)

2. 이항 & 연산자는 정수 계열 형식(integral types)과 bool에 대해 미리 정의되어 있습니다.

3. 정수 계열 형식의 경우 & 연산자는 피연산자의 비트 논리 AND를 계산합니다.

4. bool 피연산자의 경우 & 연산자는 논리 AND를 계산합니다.

5. 즉, 두 피연산자가 모두 true인 경우에만 결과가 true 입니다.

6. & 연산자는 첫째 피연산자의 값에 상관없이 두 연산자를 모두 계산합니다.


int i = 0; if (false & ++i == 1) { // i는 증가되지만 조건 식은 false로 평가되어서 이 블록은 실행되지 않습니다. }


7. 사용자 정의 형식으로 이항 & 연산자를 오버로드할 수 있습니다.(operator 참조)

8. 정수 계열 형식에 대한 연산은 일반적으로 열거형(enumeration)에서 허용됩니다.

9. 이항 연산자가 오버로드되면 해당 대입 연산자(corresponding assignment operator)도 암시적으로 오버로드됩니다.


class BitwiseAnd { static void Main() { // 다음 두 문은 논리 AND를 수행합니다.. Console.WriteLine(true & false); Console.WriteLine(true & true); // 다음 라인은 F8 (1111 1000) 과 3F (0011 1111) 를 비트 AND 수행합니다. // 1111 1000 // 0011 1111 // --------- // 0011 1000 or 38 Console.WriteLine("0x{0:x}", 0xf8 & 0x3f); } } // Output: // False // True // 0x38





* 연산자

    - 곱하기(multiplication) 연산자 (*)는 피연산자의 곱(product)을 계산합니다.

    - 또한 포인터를 읽고 쓸 수 있는 역참조(dereference) 연산자 역할을 합니다.


1. 모든 숫자 형식에는 * 연산자가 미리 정의되어 있습니다.

2. * 연산자는 포인터 형식의 선언과 역참조에도 사용됩니다.

3. * 연산자는 unsafe 컨텍스트에서만 사용될 수 있고, /unsafe 컴파일러 옵션이 필요합니다.

4. 역참조 연산자는 또한 간접 참조(indirection) 연산자라고도 합니다.

5. 사용자 정의 형식으로 이항 * 연산자를 오버로드할 수 있습니다.

6. 이항 연산자가 오버로드되면 해당 대입 연산자도 암시적으로 오버로드 됩니다.


class Multiply
{
    static void Main() 
    {
        Console.WriteLine(5 * 2);
        Console.WriteLine(-.5 * .2);
        Console.WriteLine(-.5m * .2m); // decimal type
    }
}
    /*
Output
    10
    -0.1
    -0.10
*/


public class Pointer
{
    unsafe static void Main()
    {
        int i = 5;
        int* j = &i;
        System.Console.WriteLine(*j);
    }
}
/*
Output:
5
*/





/ 연산자


    - 나누기 연산자(division operator) (/)는 첫째 피 연산자에서 둘째 피연산자를 나눕니다.

    - 모든 숫자 형식(All numeric types)에는 / 연산자가 미리 정의되어 있습니다.


1. 사용자 정의 형식으로 첫째 피연산자에서 둘째 피연산자를 나눕니다.

2. / 연산자를 오버로드하면 /= 연산자도 암시적으로 오버로드됩니다.

3. 두 정수(two integers)에 대해 나누기를 수행하면 결과는 항상 정수입니다.

4. 예를 들어 7 / 3 의 결과는 2입니다.

5. 7 / 3 의 나머지(remainder)를 확인(determine)하려면 나머지 연산자 (%) 를 사용합니다.

6. 몫(quotient)을 유리수(rational number)나 분수(fraction)로 가져오려면 피제수(dividend) 형식이나 divisor(제수) 형식을 float 이나 double로 지정합니다.

7. 다음 에제와 같이 숫자를 소수점의 오른쪽에 놓아서 피제수 또는 제수를 소수점 형태로 표현한다면 암시적으로 형식을 지정할 수 있습니다.


class Division { static void Main() { Console.WriteLine("\nDividing 7 by 3."); // 정수 몫은 2, 나머지는 1. Console.WriteLine("Integer quotient: {0}", 7 / 3); Console.WriteLine("Negative integer quotient: {0}", -7 / 3); Console.WriteLine("Remainder: {0}", 7 % 3); // Force a floating point quotient. float dividend = 7; Console.WriteLine("Floating point quotient: {0}", dividend / 3); Console.WriteLine("\nDividing 8 by 5."); // 정수 몫은 1, 나머지는 3. Console.WriteLine("Integer quotient: {0}", 8 / 5); Console.WriteLine("Negative integer quotient: {0}", 8 / -5); Console.WriteLine("Remainder: {0}", 8 % 5); // 부동소수점으로 암시적 표현 Console.WriteLine("Floating point quotient: {0}", 8 / 5.0); } } // Output: //Dividing 7 by 3. //Integer quotient: 2 //Negative integer quotient: -2 //Remainder: 1 //Floating point quotient: 2.33333333333333 //Dividing 8 by 5. //Integer quotient: 1 //Negative integer quotient: -1 //Remainder: 3 //Floating point quotient: 1.6





% 연산자


    - % 연산자는 첫째 피연산자를 둘째 피연산자로 나눈 나머지를 계산합니다.

    - 모든 숫자 형식은 나머지 연산자가 미리 정의되어 있습니다.


1. 사용자 정의 형식으로 % 연산자를 오버로드 할 수 있습니다.

2. 이항 연산자가 오버로드되면 해당 대입 연산자도 암시적으로 오버로드됩니다.


class MainClass6
{
    static void Main()
    {
        Console.WriteLine(5 % 2);       // int
        Console.WriteLine(-5 % 2);      // int
        Console.WriteLine(5.0 % 2.2);   // double
        Console.WriteLine(5.0m % 2.2m); // decimal
        Console.WriteLine(-5.2 % 2.0);  // double
    }
}
/*
Output:
1
-1
0.6
0.6
-1.2
*/





+ 연산자


    - + 연산자는 단항 연산자로 사용하거나 이항 연산자로 사용할 수 있습니다.


1. 단항 + 연산자는 모든 숫자 형식에 대해 미리 정의되어 있습니다.

2. 숫자 형식에 대한 단항 + 연산자의 결과는 단순히 피연산자의 값입니다.

3. 이항 + 연산자는 숫자 형식과 문자열 형식에 대해 미리 정의되어 있습니다.

4. 숫자 형식의 경우, + 연산자는 두 피연산자의 합을 계산합니다.

5. 하나 또는 두 피연산자가 문자열 형식인 경우 + 연산자는 피연산자를 나타내는 문자열을 연결합니다.

6. 또한 대리자 형식도 이항 + 연산자를 제공합니다. 이 경우 대리자 연결을 수행합니다.

7. 사용자 정의 형식으로 단항 + 연산자와 이항 + 연산자를 오버로드할 수 있습니다.

8. 정수 계열 형식에 대한 연산은 일반적으로 열거형에서 허용됩니다.


class Plus { static void Main() { Console.WriteLine(+5); // unary plus Console.WriteLine(5 + 5); // addition Console.WriteLine(5 + .5); // addition Console.WriteLine("5" + "5"); // string concatenation Console.WriteLine(5.0 + "5"); // string concatenation // double 형에서 string 형으로 자동 변환된다. } } /* Output: 5 10 5.5 55 55 */





- 연산자


    - - 연산자는 단항 연산자로 사용하거나 이항 연산자로 사용할 수 있습니다.


1. 단항 - 연산자는 모든 숫자 형식에 대해 미리 정의되어 있습니다.

2. 숫자 형식에 대한 단항 - 연산의 결과는 피연산자의 숫자 부정(negation)입니다.

3. 이항 - 연산자는 모든 숫자 형식과 열거 형식에 대해 첫째 피연산자에서 두번재 피연산자를 빼도록 미리 정의되어 있습니다.

4. 또한 대리자 형식도 이항 - 연산자를 제공합니다. 이 경우에는 대리자 제거를 수행합니다.

5. 사용자 정의 형식으로 단항 - 연산자와 이항 - 연산자를 오버로드할 수 있습니다.


class MinusLinus
{
    static void Main()
    {
        int a = 5;
        Console.WriteLine(-a);
        Console.WriteLine(a - 1);
        Console.WriteLine(a - .5);
    }
}
/*
Output:
-5
4
4.5
*/





<< 연산자


    - 왼쪽 시프트 연산자(left-shift operator)는 첫째 피연산자를 둘째 피연산자에서 지정한 비트 수만큼 비트 다누이로 왼쪽으로 이동합니다.

    - 두번째 피연산자 형식은 int 또는 int에 대한 미리 정의된 암시적 숫자 변환이 있는 형식이어야 합니다.


1. 첫째 피연산자가 int 또는 uint 형식이면 시프트 횟수는 둘째 피연산자의 하위 5비트로 지정됩니다. 즉, 실제 시프트 횟수는 0-31 비트입니다.

2. 첫째 피연산자가 64비트 용량의 long 또는 ulong 형식이면 시프트 횟수는 둘째 피연산자의 하위 6비트로 지정됩니다. 즉, 실제 시프트 횟수는 0-63 비트입니다.

3. 시프트 후 첫번째 피연산자의 형식 범위 내에 없는 상위 비트는 무시되고 하위의 빈 비트는 0으로 채워집니다.

4. 시프트 후 첫번째 피연산자의 형식 범위 내에 없는 상위 비트는 무시되고 하위의 빈 비트는 0으로 채워집니다. 시프트 연산은 오버플로를 일으키지 않습니다.

5. 사용자 정의 형식으로 << 연산자를 오버로드할 수 있습니다. 이 경우 첫째 피연산자의 형식은 사용자 정의 형식이어야 하며 둘째 피연산자의 형식은 int여야 합니다.

6. 이항 연산자가 오버로드되면 해당 대입 연산자도 암시적으로 오버로드됩니다.


class MainClass11 { static void Main() { int i = 1; long lg = 1; // i를 1비트 왼쪽으로 시프트합니다. 결과는 2입니다. Console.WriteLine("0x{0:x}", i << 1); // 2진수로, 33은 100001 입니다. // 하위 5비트의 값은 1이기 때문에 시프트의 결과는 2입니다. Console.WriteLine("0x{0:x}", i << 33); // lg의 형식은 long입니다. long 형식이기때문에 시프트는 하위 6비트의 값입니다. // 하위 6비트의 값은 100001 (33) 이기 때문에 왼쪽으로 33 시프트 됩니다. // In binary: 10 0000 0000 0000 0000 0000 0000 0000 0000 // In hexadecimal: 2 0 0 0 0 0 0 0 0 Console.WriteLine("0x{0:x}", lg << 33); } } /* Output: 0x2 0x2 0x200000000 */


'프로그래밍 > C#' 카테고리의 다른 글

C# 키워드 O~S  (0) 2016.05.31
C# 키워드 F~N  (0) 2016.05.21
C# 키워드 A-E  (0) 2016.05.13
C# 총정리  (0) 2016.04.19
정리  (0) 2016.04.09
:
Posted by 지훈2
2016. 4. 19. 22:49

C# 총정리 프로그래밍/C#2016. 4. 19. 22:49

구조체 (struct)


1. 구조체는 클래스와 동일한 구문을 대부분 공유하지만 클래스보다 제한적입니다.

2. 구조체 선언 내에서 필드는 const 또는 static으로 선언한 경우에만 초기화할 수 있습니다.

3. 구조체는 할당 시 복사됩니다. 구조체가 새 변수에 할당되면 모든 데이터가 복사되고, 새 복사본을 수정해도 원래 복사본의 데이터는 변경되지 않습니다. Dictionary<string, myStruct>와 같은 값 형식의 컬렉션을 사용할 때 이것이 중요합니다.

4. 구조체는 값 형식이고 클래스는 참조 형식입니다.

5. 클래스와 달리 구조체는 new 연산자를 사용하지 않고 인스턴스화할 수 있습니다.

6. 구조체는 매개변수가 있는 생성자를 선언할 수 있습니다.

7. 구조체는 다른 구조체 또는 클래스에서 상속될 수 없으며, 클래스의 기본 클래스가 될 수도 없습니다. 모든 구조체는 System.Object를 상속하는 System.ValueType에서 직접 상속합니다.

8. 구조체는 인터페이스를 구현할 수 있습니다.

9. 구조체를 nullable 형식으로 사용할 수 있고 여기에 null 값을 할당할 수 있습니다.

https://msdn.microsoft.com/ko-kr/library/saxz13w4.aspx





구조체 사용 (struct)


1. 매개 변수가 없는 생성자를 정의하면 오류가 발생합니다.

2. 구조체 본문에서 인스턴스 필드를 초기화해도 오류가 발생합니다.

3. 구조체의 멤버 변수를 초기화 하려면 생성자를 사용하거나 개별적 액세스로 초기화할 수 있습니다.

4. new 연산자를 사용하여 구조체 객체를 생성하면 생성자가 호출됩니다.

5. 클래스와 달리 new 연산자를 사용하지 않고 인스턴스화할 수 있습니다. 이 경우 생성자는 호출되지 않으므로 개별적으로 모든 필드를 초기화 해야합니다.

6. 클래스와 다르게 상속이 없습니다. 그러나 기본 클래스 Object에서 상속할 수 있습니다.

7. 구조체는 클래스에서 인터페이스를 구현하는 것과 동일한 방식으로 인터페이스를 구현할 수 있습니다.

8. 구조체는 값 형식인 반면 클래스는 참조 형식입니다.

9. 참조 형식 구문이 필요한 경우가 아니라면 작은 클래스는 구조체로 대신 선언하면 시스템에서 보다 효율적으로 처리할 수 있습니다.


예제1) 기본 생성자와 매개변수가 있는 생성자로 struct 초기화 하는 방법

public struct CoOrds

{
    public int x, y;

    public CoOrds(int p1, int p2)
    {
        x = p1;
        y = p2;
    }
}


// Declare and initialize struct objects.

class TestCoOrds
{
    static void Main()
    {
        // Initialize:   
        CoOrds coords1 = new CoOrds();
        CoOrds coords2 = new CoOrds(10, 10);

        // Display results:
        Console.Write("CoOrds 1: ");
        Console.WriteLine("x = {0}, y = {1}", coords1.x, coords1.y);

        Console.Write("CoOrds 2: ");
        Console.WriteLine("x = {0}, y = {1}", coords2.x, coords2.y);

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
    CoOrds 1: x = 0, y = 0
    CoOrds 2: x = 10, y = 10
*/


예제2) new 연산자를 사용하지 않고 객체 생성 방법

public struct CoOrds

{
    public int x, y;

    public CoOrds(int p1, int p2)
    {
        x = p1;
        y = p2;
    }
}


  // Declare a struct object without "new."
class TestCoOrdsNoNew
{
    static void Main()
    {
        // Declare an object:
        CoOrds coords1;

        // Initialize:
        coords1.x = 10;
        coords1.y = 20;

        // Display results:
        Console.Write("CoOrds 1: ");
        Console.WriteLine("x = {0}, y = {1}", coords1.x, coords1.y);

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
// Output: CoOrds 1: x = 10, y = 20

https://msdn.microsoft.com/ko-kr/library/0taef578.aspx





배열


1. 배열 데이터 구조에 동일한 형식의 변수를 여러 개 저장할 수 있습니다.

2. 문법 : type[] arrayName;



Class TestArraysClass

{

    static void Main()

    {

        // 1차원 배열 선언

        int[] array1 = new int[5];


        // 선언과 값 설정

        int array2 = new int[] { 1, 3 ,5, 7, 9 };


        // 다른 방식

        int[] array3 = { 1, 2, 3, 4, 5, 6 };


        // 2차원 배열 선언

        int[,] multiDimensionalArray1 = new int[2, 3];


        // 선언과 값 설정

        int[,] multiDimensionalArray2 = { { 1, 2, 3 }, { 4, 5, 6 } };


        // 가변 배열 선언

        int[][] jaggedArray = new int[6][];


        // 가변 배열에서 첫번째 배열에 값 설정

        jaggedArray[0] = new int[4] { 1, 2, 3 ,4 };

    }

}

 


3. 배열은 1차원, 다차원, 가변 배열이 있습니다.

4. 차원 수와 각 차원의 길이는 배열 인스턴스가 생성될 때 만들어집니다. 이러한 값은 인스턴스의 수명 동안 변경할 수 없습니다.

5. 숫자 배열 요소에는 0이, 참조 요소에는 null이 기본값으로 설정됩니다.

6. 배열의 인덱스는 0부터 시작합니다. n개의 요소가 있는 배열의 인덱스는 0부터 n-1까지입니다.

7. 배열 요소는 배열 형식을 포함하여 모든 형식이 될 수 있습니다.

8. 배열 형식은 Array 추상 기본 형식에서 파생된 참조 형식입니다.

9. 이 형식은 IEnumerable 및 IEnumerable<T>을 구현하므로 C#의 모든 배열에 foreach 반복을 사용할 수 있습니다.

https://msdn.microsoft.com/ko-kr/library/9b9dty7d.aspx





1차원 배열



1. 5개의 정수를 포함하는 1차원 배열 선언

   int[] array = new int[5];

이 배열은 array[0]에서 array[4]까지의 요소가 있습니다. 배열을 생성하고 배열 요소를 기본값으로 초기화하려면 new 연산자를 사용합니다. 이 예제에서는 모든 배열 요소를 0으로 초기화합니다.


2. 문자열 배열 선언

   string[] stringArray = new string[6];


3. 배열 초기화

    int[] array1 = new int[] { 1, 3, 5, 7, 9 };

선언 시 배열을 초기화할 수 있으며, 이런 경우 차수는 초기화 목록의 요소 수로 지정되므로 별도로 지정할 필요가 없습니다.


4. 문자열 배열 초기화 선언

    string[] weekDays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };


5. 선언 시 배열을 초기화할 경우 다음과 같이 단축적으로 할 수 있습니다.

    int[] array2 = { 1, 3, 5, 7, 9 };

    string[] weekDays2 = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };


6. 배열 변수를 초기화하지 않고 선언할 수 있지만 이러한 변수에 배열을 할당하려면 new 연산자를 사용해야 합니다.

    int[] array3;

    array3 = new int[] { 1, 3, 5, 7, 9 }; // OK

    // array3 = { 1, 3, 5, 7, 9 } // Error


7. 값 형식 및 참조 형식 배열

    SomeType[] array4 = new SomeType[10];

SomeType 배열을 선언하는데 참조 형식인 경우 각 요소는 null 참조로 초기화 됩니다.

https://msdn.microsoft.com/ko-kr/library/0a7fscd0.aspx





c# 연산자




<기본 연산자>


1. x.y

   - 도트 연산자(.), 멤버 엑세스에 사용


Class Simple

{

    public int a;

    public void b()

    {

    }

}

Simple s = new Simple();

s.a = 6;

s.b();

// 변수 s 에는 a 및 b 두 멤버가 있습니다. 이들 멤버에 엑세스 하기 위해 도트 연산자를 사용합니다.




System.Console.WriteLine("hello");

// 해당 멤버가 속한 네임스페이스나 인터페이스 등에서도 사용합니다.




namespace Example2

{

    class console

    {

        public static void Write(string s) {}

    }

}

namespace Example1

{
    using System;

    using Example2;

    class C

    {

        void M()

        {

            System.Console.WriteLine("hello");

            Example2.Console.WriteLine("hello");

        }

    }

}

// 식별자가 모호할 경우 사용





2. x?.y

   - null 조건부 멤버 엑세스(?.), 인덱스 작업(?[)null 검사를 위한 코드의 양을 줄이는데 도움이 된다.


 int? length = customers?.Length;    // customers 가 null 이면 null

 Customer first = customers?[0];    // customers 가 null 이면 null

 int? count = customers?[0]?.Orders?.Count();    // customers, [0], Orders 가 null 이면 null

  조건부 멤버 엑세스 및 인덱스 작업 체인의 한 작업이 null을 반환하면 나머지 부분은 중지됩니다.


 A?.B?.C?[0] ?? E

 A?.B?.C?[0] == E

// Null 조건부 연산자


대리자 호출 예제

예전 방식

var handler = this.PropertyChanged;

if (handler  != null)

    handler (...)


새로운 방식

PropertyCanged?.Invoke(e)

  새로운 방식은 컴파일러가 PropertyChanged를 한 번만 평가하는 코드를 생성하고 결과를 임시 변수에 유지하기때문에 스레드로부터 안전합니다.




3. f(x)

    - 괄호 연산자, 함수 호출

    - 식에서 연산의 순서를 지정하기 위해 사용

    - 캐스팅은 구문을 모호하게 할 수 있습니다. 예를 들면 (x)-y는 -y를 x 형식으로 캐스팅하는 의미로 해석될 수 있고, x-y의 가감식으로 해석될 수 있습니다.


1) 캐스팅 또는 형식 변황을 지정합니다.


double x = 1234.7;

int a;

a = (int)x;


2) 메서드 또는 대리자 호출


TestMethod();





4. a[x]

    - 집계 객체 인덱싱

    - 대괄호([])는 배열, 인덱서 및 특성에 사용합니다 또한 포인터에도 사용합니다.


1) 배열 형식

int[] fib; // int 형 배열

fib = new int[100]; // int 형 배열 100개 생성


fib[0] = fib[1] = 1;

for (int i = 2; i < 100; ++i)

    fib[i] = fib[i - 1] + fib[i - 2];

// 배열 인덱스가 범위를 벗어나면 예외가 throw 됩니다.


2) Hashtable 형식

System.Collections.hashtable h = new System.Collections.Hashtable();

h["a"] = 123; // a 를 인덱스로 사용


3) 특성을 지정

[Conditional("DEBUG")]

void TraceMethod() {}


4) 포인터의 인덱스 참조에 사용할 수 있습니다.

unsafe void M()

{

    int[] nums = { 0, 1, 2, 3 ,4, 5 };

    fixed ( int* p = nums )

    {

        p[0] = p[1] = 1;

        for ( int i=2; i<100; ++i )

            p[i] = p[i-1] + p[i-2];

    }

}




5. a?[x]

    - null 조건부 인덱싱. 왼쪽 피연산자가 null인 경우 null을 반환합니다.

    - 2번 x?.y 참조




6. x++

    - 후위 증가. x의 값을 반환하고 x에 1을 더합니다.


Class MainClass

{

    static void Main()

    {

        double x;

        x = 1.5;

        Console.WriteLine(++x);  // 2.5

        x = 1.5;

        Console.WriteLine(x++);  // 1.5

        console.WriteLine(x);  // 2.5

    }





7. x--

    - 후위 감소. x의 값을 반환하고 x에 1을 뺍니다.


Class MainClass

{

    static void Main()

    {

        double x;

        x = 1.5;

        Console.WriteLine(--x);  // 0.5

        x = 1.5;

        Console.WriteLine(x--);  // 1.5

        Console.WriteLine(x);  // 0.5

    }

}





8. New

    - 형식 인스턴스화


1) 객체를 만들고 생성자를 호출하는 데 사용됩니다.

    Class1 obj = new Class1()


2) 익명 형식의 인스턴스를 만드는 데도 사용됩니다.

    var query = from cust in customers

                    select new {Name = cust.Name, Address = cust.Primaryaddress};


3) 값 형식에 대한 기본 생성자를 호출하는 데도 사용됩니다.

    int i = new int();  // int 형식의 기본값인 0으로 초기화됩니다.

    int i = 0;

    // 두 문의 결과는 같다.


    - 모든 값 형식에는 암시적으로 공용 기본 생성자가 포함되기 때문에 구조체에 대한 기본 생성자를 선언하면 오류가 발생합니다.

    - 구조체는 매개변수가 있는 생성자를 선언하여 그 초기값을 설정할 수 있지만 이 방법은 기본값이 아닌 다른 값이 필요한 경우에만 사용해야 합니다.

    - 구조체와 같은 값 형식 개체는 스택에 만들어지고 클래스 같은 참조 형식 개체는 힙에 만들어집니다.

    - new 연산자는 오버로드 되지 않습니다.

    - new 연산자가 메모리 할당에 실패하면 OutOfMemoryexception 예외를 던집니다.



struct SampleStruct

{

   public int x;

   public int y;


   public SampleStruct(int x, int y)

   {

      this.x = x;

      this.y = y;

   }

}


class SampleClass

{

   public string name;

   public int id;


   public SampleClass() {}


   public SampleClass(int id, string name)

   {

      this.id = id;

      this.name = name;

   }

}


class ProgramClass

{

   static void Main()

   {

      // 기본 생성자를 사용하여 객체 생성

      SampleStruct Location1 = new SampleStruct();

      SampleClass Employee1 = new SampleClass();


      // Display values:

      Console.WriteLine("Default values:");

      Console.WriteLine("   Struct members: {0}, {1}",

             Location1.x, Location1.y);

      Console.WriteLine("   Class members: {0}, {1}",

             Employee1.name, Employee1.id);


      // 매개변수를 가진 생성자를 사용하여 객체 생성

      SampleStruct Location2 = new SampleStruct(10, 20);

      SampleClass Employee2 = new SampleClass(1234, "Cristina Potra");


      // Display values:

      Console.WriteLine("Assigned values:");

      Console.WriteLine("   Struct members: {0}, {1}",

             Location2.x, Location2.y);

      Console.WriteLine("   Class members: {0}, {1}",

             Employee2.name, Employee2.id);

   }

}

/*

Output:

Default values:

   Struct members: 0, 0

   Class members: , 0

Assigned values:

   Struct members: 10, 20

   Class members: Cristina Potra, 1234

*/





9. Typeof

    - 피연산자(operand)를 나타내는 System.Type 개체를 반환합니다.

    - System.Type 객체를 얻는 데 사용됩니다.

    - typeof 연산자는 오버로드되지 않습니다.


typyof 형식

    System.Type type = typeof(int);


GetType() 메서드 사용

    int i = 0;

    System.Type type = i.GetType();


    

    - typeof 연산자는 열린 제네릭 형식에도 사용할 수 있습니다.


string s = method.ReturnType.GetInterface(typeof(System.Collections.Generic.IEnumerable<>).FullName);



메소드 정보 얻기

public class ExampleClass

{

   public int sampleMember;

   public void SampleMethod() {}


   static void Main()

   {

      Type t = typeof(ExampleClass);

      // Alternatively, you could use

      // ExampleClass obj = new ExampleClass();

      // Type t = obj.GetType();


      Console.WriteLine("Methods:");

      System.Reflection.MethodInfo[] methodInfo = t.GetMethods();


      foreach (System.Reflection.MethodInfo mInfo in methodInfo)

         Console.WriteLine(mInfo.ToString());


      Console.WriteLine("Members:");

      System.Reflection.MemberInfo[] memberInfo = t.GetMembers();


      foreach (System.Reflection.MemberInfo mInfo in memberInfo)

         Console.WriteLine(mInfo.ToString());

   }

}

/*

 Output:

    Methods:

    Void SampleMethod()

    System.String ToString()

    Boolean Equals(System.Object)

    Int32 GetHashCode()

    System.Type GetType()

    Members:

    Void SampleMethod()

    System.String ToString()

    Boolean Equals(System.Object)

    Int32 GetHashCode()

    System.Type GetType()

    Void .ctor()

    Int32 sampleMember

*/


숫자 계산을 위한 type 확인을 위해 GetType 메서드 사용

class GetTypeTest

{

    static void Main()

    {

        int radius = 3;

        Console.WriteLine("Area = {0}", radius * radius * Math.PI);

        Console.WriteLine("The type is {0}",

                          (radius * radius * Math.PI).GetType()

        );

    }

}

/*

Output:

Area = 28.2743338823081

The type is System.Double

*/





10. checked

    - 정수 계열 형식의 산술 연산 및 변환에 대한 오버플로 검사를 명시적으로 활성화

    - 기본적으로 식이 상수 값만으로 되어 있고 형식의 범위를 초과 한다면 컴파일러 오류가 발생합니다.

    - 식이 상수가 아닌 값을 하나 이상 포함하는 경우 컴파일러가 오버플로를 검색하지 않습니다.


// 정수형의 최대치인 2147483647을 넘는다면 컴파일러 에러 CS0220이 발생합니다.

int i1 = 2147483647 + 10;


// 변수 ten 이 포함된 다음 예제는 컴파일러 에러를 발생시키지 않습니다.

int ten = 10;

int i2 = 2147483647 + 10;

Console.WriteLine(i2);  // 결과 : -2,147,483,639


    - 기본적으로 상수가 아닌 이러한 식에서는 런타임 에러 오버플로가 검사되지 않습니다.

    - 컴파일러 옵션, 환경 구성 또는 checked 키워드 사용을 통해 오버플로 검사를 활성화할 수 있습니다.

    - 다음 예제에서는 checked 식이나 checked 블록을 사용하여 오버플로를 검색하는 방법을 보여줍니다.


// checked 식

Console.WriteLine(checked(2147483647 + ten));


// checked 블럭

checked

{

    int i3 = 2147483647 + ten;

    Console.WriteLine(i3);

}


    - unchecked 키워드는 오버플로 검사를 막기 위해 사용될 수 있습니다.

    - 다음 예제는 checked 키워드로 오버플로 검사 예제입니다.


class OverFlowTest

{

    // int 형 최대값을 maxIntValue 에 설정합니다.

    static int maxIntValue = 2147483647;


    // checked 식

    static int CheckedMethod()

    {

        int z = 0;

        try

        {

            // 다음 라인은 checked 를 사용했기 때문에 예외를 발생시킵니다.

            z = checked(maxIntValue + 10);

        }

        catch (System.OverflowException e)

        {            

            Console.WriteLine("CHECKED and CAUGHT:  " + e.ToString());

        }

        return z;

    }


    // unchecked 식.

    static int UncheckedMethod()

    {

        int z = 0;

        try

        {

            // 다음 계산은 unchecked 이기 때문에 예외를 발생시키지 않습니다.

            z = maxIntValue + 10;

        }

        catch (System.OverflowException e)

        {  

            Console.WriteLine("UNCHECKED and CAUGHT:  " + e.ToString());

        }

        // 오버플로가 체크되지 않았기 때문에 2147483647 + 10 은 -2147483639 가 반환됩니다.

        return z;

    }


    static void Main()

    {

        Console.WriteLine("\nCHECKED output value is: {0}",

                          CheckedMethod());

        Console.WriteLine("UNCHECKED output value is: {0}",

                          UncheckedMethod());

    }

    /*

   Output:

   CHECKED and CAUGHT:  System.OverflowException: Arithmetic operation resulted

   in an overflow.

      at ConsoleApplication1.OverFlowTest.CheckedMethod() 


   CHECKED output value is: 0

   UNCHECKED output value is: -2147483639

 */

}


https://msdn.microsoft.com/ko-kr/library/6a71f45d.aspx





11. unchecked

1. 정수 계열 형식의 산술 연산 및 변환에 대한 오버플로 검사를 비활성화하는 데 사용됩니다.

2. unchecked 컨텍스트 내에서는, 식의 결과 값이 대상 형식의 범위를 벗어나는 경우, 오버플로 플래그가 세워지지 않습니다.

3. 예를 들어, 다음 예제의 계산은 unchecked 블록이나 식의 안쪽에서 수행되므로 결과값이 정수로서는 너무 크다는 사실이 무시되고, int1에 값 -2,147,483,639이 할당됩니다.

unchecked
{
    int1 = 2147483647 + 10;
}
int1 = unchecked(ConstantMax + 10);


3. unchecked 환경을 제거하면 컴파일 오류가 발생합니다.

4. 식의 모든 항이 상수이기 때문에 컴파일 시점에 오버플로를 감지할 수 있습니다.

5. 비상수 항을 포함하는 식은 기본적으로 컴파일 시점과 실행 시점이 검사되지 않습니다.

6. 오버플로를 검사하는 작업은 시간이 걸리기 때문에 오버플로 위험이 없는 경우 unchecked 코드를 사용하면 성능을 향상시킬 수 있습니다.

7. 그러나 오버플로가 발생할 수 있는 경우 checked 환경을 사용해야 합니다.

class UncheckedDemo

{ static void Main(string[] args) { // int.MaxValue is 2,147,483,647. const int ConstantMax = int.MaxValue; int int1; int int2; int variableMax = 2147483647; // 다음 문은 기본적으로 컴파일 타임에 체크되고, 컴파일 되지 않습니다. //int1 = 2147483647 + 10; //int1 = ConstantMax + 10; // int1에 할당을 하고 컴파일과 실행을 하려면 unchecked 블록이나 식 안에 두어야 합니다. // 다음 식은 컴파일되고 실행 됩니다. unchecked { int1 = 2147483647 + 10; } int1 = unchecked(ConstantMax + 10); // 2,147,483,647 과 10 의 합은 -2,147,483,639 로 표시됩니다. Console.WriteLine(int1); // 다은 문은 기본적으로 컴파일 타임과 실행 타임에 체크되지 않습니다. // 식이 변수 variableMax를 포함하기 때문입니다. // 오버플로를 발생시키지만 오버플로로 발견되지는 않습니다. 문은 컴파일되고 실행됩니다. int2 = variableMax + 10; // 다시, 2,147,483,647 과 10 의 합계가 -2,147,483,639 로 표시됩니다. Console.WriteLine(int2); // 실행 타임때 int2에 할당에 대한 오버플로를 잡으려면 checked 블록이나 식 안에 두어야 합니다. // 다음 문은 컴파일 되지만 실행 타임에 오버플로 예외를 일으킵니다. checked { //int2 = variableMax + 10; } //int2 = checked(variableMax + 10); // Unchecked 섹션은 checked 환경에서 자주 사용되는데 // 오버플로 예외를 예상하지 못한 코드의 부분에서의 성능 향상을 위해서 입니다. checked { // 오버플로를 발생시킬 수도 있는 코드가 checked 환경에서 실행된다. unchecked { // 이 섹션은 성능이 우선되고 오버플로가 발생하지 않을 것을 확신할 때 적절합니다. } // 추가 체크 코드 } } }





12. Delegate (대리자)


1. 코드 블럭을 대리자 매개변수로 넘기는 두가지 방법

// 클릭 이벤트 핸들러 만듦
button1.Click += delegate(System.Object o, System.EventArgs e)
                   { System.Windows.Forms.MessageBox.Show("Click!"); };


// 대리자 생성 delegate void Del(int x); // 무명 메서드를 사용해서 대리자 인스턴스 만듦 Del d = delegate(int k) { /* ... */ };


2. 무명 메서드를 사용하면 별도의 메서드를 만들 필요가 없으므로 대리자의 인스턴스를 만드는데에 따른 코드 오베헤드가 없다.

3. 다음 코드는 스레드에 실행 코드가 포함되어 있으므로 별도의 대리자의 메서드를 만들 필요가 없다.

void StartThread()
{
    System.Threading.Thread t1 = new System.Threading.Thread
      (delegate()
            {
                System.Console.Write("Hello, ");
                System.Console.WriteLine("World!");
            });
    t1.Start();
}


4. 무명 메서드 블록 안에서 블록 밖으로나 안을 대상으로 goto, break, 또는 continue와 같은 점프 문을 사용하면 오류가 발생한다.

5. 지역 변수 및 매개 변수의 범위에 무명 메서드 선언이 포함되는 경우 이러한 변수를 무명 메서드의 외부 변수라고 합니다.

6. 다음 코드에서 n은 외부 변수 입니다.

7. 무명 메서드를 참조하는 대리자가 가비지 수집이 될 때까지 외부 변수 n의 수명은 확장합니다.

8. 무명 메서드에서는 외부 범위의 ref 또는 out 매개 변수에 액세스할 수 없습니다.

9. 무명 메서드는 is 연산자의 왼쪽에 사용할 수 없습니다.

int n = 0;

Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };


10. 다음 예제에서는 대리자를 인스턴스화하는 두 가지 방법을 보여 줍니다.

    - 대리자를 무명 메서드에 연결

    - 대리자를 명명된 메서드(named method)에 연결



delegate void Printer(string s); class TestClass { static void Main() { // 무명 메서드를 사용해서 대리자 형식을 인스턴스화 Printer p = delegate(string j) { System.Console.WriteLine(j); }; // 무명 대리자 호출로부터의 결과 p("The delegate using the anonymous method is called."); // 명명된 메서드 "DoWork" 를 사용해서 대리자 인스턴스화 p = new Printer(TestClass.DoWork); // 구식 스타일 대리자 호출로부터의 결과 p("The delegate using the named method is called."); } // 명명된 대리자와 연결된 메서드 static void DoWork(string k) { System.Console.WriteLine(k); } } /* Output: The delegate using the anonymous method is called. The delegate using the named method is called. */



13. sizeof

1. 관리되지 않는 형식에 대한 바이트 단위의 크기를 가져오는데 사용됩니다.

   - 열거형 형식

   - 포인터 형식

   - 참조 형식인 필드나 속성을 포함하지 않는 사용자 정의 구조체

2. 다음 예제에서는 int의 크기를 검색하는 방법을 보여줍니다.

// 상수 값 4:
int intSize = sizeof(int); 

3. C# 2.0부터는 기본 제공 형식(built-in types)에 sizeof를 적용할 때 unsafe 모드를 사용하지 않아도 됩니다.

4. sizeof 연산자는 오버로드되지 않습니다.

5. sizeof 연산자가 반환하는 값은 int 형식입니다.

6. 다음 표는 특정 기본 제공 형식을 피연산자로 사용하는 sizeof식 대신 사용되는 상수 값을 보여줍니다.

상수 값

sizeof(sbyte)

1

sizeof(byte)

1

sizeof(short)

2

sizeof(ushort)

2

sizeof(int)

4

sizeof(uint)

4

sizeof(long)

8

sizeof(ulong)

8

sizeof(char)

2(유니코드)

sizeof(float)

4

sizeof(double)

8

sizeof(decimal)

16

sizeof(bool)

1

7. 구조체를 포함한 다른 모든 형식의 경우에는 안전하지 않은 코드 블록에서만 sizeof 연산자를 사용할 수 있습니다.

8. Marshal.SizeOf 메서드를 사용할 수 있지만 이 메서드가 반환하는 값이 sizeof가 반환하는 값과 항상 같지는 않습니다.

9. Marshal.SizeOf는 형식이 마샬링된 후의 크기를 반환한다.

10. 하지만 sizeof는 패딩을 포함하여 공용 언어 런타임에서 할당된 크기를  반환합니다.

class MainClass { // unsafe는 원시형에는 필요치 않다.(unsafe not required for primitive types) static void Main() { Console.WriteLine("The size of short is {0}.", sizeof(short)); Console.WriteLine("The size of int is {0}.", sizeof(int)); Console.WriteLine("The size of long is {0}.", sizeof(long)); } } /* Output: The size of short is 2. The size of int is 4. The size of long is 8. */






string


1. 문자열은 값이 텍스트인 string 형식의 개체입니다.

2. 내부적으로 텍스트는 Char 객체의 순차적(sequential) 읽기 전용 컬렉션으로 저장됩니다.

3. C# 문자열의 끝에는 null 종결 문자가 없습니다.

4. C# 문자열은 null 문자(\n)을 제한 없이 포함할 수 있습니다.

5. 문자열의 Length 속성은 유니코드 문자의 수가 아니라 포함된 Char 개체의 수를 나타냅니다.

6. 문자열에서 개별 유니코드 포인트에 액세스하려면 StringInfor 개체를 사용합니다.

// 초기화 없이 선언. string message1; // null로 초기화 string message2 = null; // 빈 문자열로 초기화 // 리터럴 "" 대신 Empty 상수 사용 string message3 = System.String.Empty; //정규 문자열 리터럴로 초기화 string oldPath = "c:\\Program Files\\Microsoft Visual Studio 8.0"; // verbatim string literal로 초기화 string newPath = @"c:\Program Files\Microsoft Visual Studio 9.0"; // 선호한다면 System.String 을 사용 System.String greeting = "Hello World!"; // 지역 변수에서 (예를 들면 메소드 몸체 내에서) // 암묵적 타입을 사용할 수 있다. var temp = "I'm still a strongly-typed System.String!"; // const 문자열을 사용하여 message4가 다른 문자열 값을 저장하는 것을 막아라. const string message4 = "You can't get rid of me!"; // char*, char[], sbyte* 로부터 문자열을 만들 때 문자열 생성자를 사용하라.

// 자세한 사항은 System.String 문서를 참조. char[] letters = { 'A', 'B', 'C' }; string alphabet = new string(letters);


7. 문자열을 문자(Char) 배열로 초기화할 경우 이외에는 new 연산자를 사용하여 문자열 개체를 만들지 마십시오.

8. Empty 상수 값으로 문자열을 초기화하여 문자열 길이가 0인 String 개체를 새로 만듭니다.

9. 길이가 0인 문자열의 문자열 리터럴 표현은 ""입니다.

10. 문자열을 null 대신 Empty 값으로 초기화하면 NullReferenceException 발생 위험을 줄일 수 있습니다.

11. 문자열에 액세스하기 전에 문자열 값을 확인하려면 static IsNullOrEmpty(string) 메서드를 사용합니다.


문자열 객체의 불변성


1. 문자열 객체는 한 번 만들어지면 변경할 수 없는 변경 불가능 객체입니다.

2. 문자열을 수정하는 것처럼 보이는 모든 string 메서드 및 C# 연산자는 실제로드는 새 문자열 객체의 결과를 반환합니다.

3. 다음 예제에서 s1과 s2의 내용이 결합되어 단일 문자열이 만들어질 때, 두 원본 문자열은 변경되지 않습니다.

4. 새 객체는 s1 변수에 할당되고 s1에 할당되었던 원래 객체는 해당 객체에 대한 참조를 유지하는 다른 변수가 없으므로 가비지 수집을 위해 해제됩니다.


string s1 = "A string is more "; string s2 = "than the sum of its chars."; // s1과 s2를 연결합니다. 이것은 실제로는 // 새 문자열 객체를 만들어서 s1에 저장하고 // 원래 객체의 참조를 해제합니다. s1 += s2; System.Console.WriteLine(s1); // 출력: A string is more than the sum of its chars.


5. 문자열 수정이 실제로는 새 문자열 생성이므로 문자열에 대한 참조를 만들 때 주의해야 합니다.

6. 문자열에 대한 참조를 만든 다음 원래 문자열을 수정할 경우 해당 참조는 문자열을 수정할 때 만든 새 객체 대신 원래 객체를 계속해서 가리킵니다.


string s1 = "Hello ";
string s2 = s1;
s1 += "World";

System.Console.WriteLine(s2);
//Output: Hello


일반 문자열 및 약어 문자열 리터럴


string columns = "Column 1\tColumn 2\tColumn 3";
//Output: Column 1        Column 2        Column 3

string rows = "Row 1\r\nRow 2\r\nRow 3";
/* Output:
  Row 1
  Row 2
  Row 3
*/

string title = "\"The \u00C6olean Harp\", by Samuel Taylor Coleridge";
//Output: "The Æolean Harp", by Samuel Taylor Coleridge


1. 문자열 텍스트에 파일 경로 등의 백슬래시 문자가 포함되는 경우에는 사용 편의성과 가독성을 향상시킬 수 있도록 약어 문자열(verbatim string)을 사용합니다.

2. 약어 문자열은 줄 바꿈 문자를 문자열 텍스트의 일부로 포함하므로 여러 줄 문자열을 초기화하는 데 사용할 수 있습니다.

3. 약어 문자열 내에 인용 부호를 포함하려면 큰 따옴표를 사용합니다.


string filePath = @"C:\Users\scoleridge\Documents\";
//Output: C:\Users\scoleridge\Documents\

string text = @"My pensive SARA ! thy soft cheek reclined
    Thus on mine arm, most soothing sweet it is
    To sit beside our Cot,...";
/* Output:
My pensive SARA ! thy soft cheek reclined
   Thus on mine arm, most soothing sweet it is
   To sit beside our Cot,... 
*/

string quote = @"Her name was ""Sara.""";
//Output: Her name was "Sara."



문자열 이스케이프 시퀀스

이스케이프 시퀀스

문자 이름

유니코드 인코딩

\'

작은따옴표

0x0027

\"

큰따옴표

0x0022

\\

백슬래시

0x005C

\0

Null

0x0000

\a

경고

0x0007

\b

백스페이스

0x0008

\f

폼 피드

0x000C

\n

줄 바꿈

0x000A

\r

캐리지 리턴

0x000D

\t

가로 탭

0x0009

\U

서로게이트 쌍에 대한 유니코드 이스케이프 시퀀스

\Unnnnnnnn

\u

유니코드 이스케이프 시퀀스

\u0041 = "A"

\v

세로 탭

0x000B

\x

가변 길이를 특징으로 하는 "\u"와 유사한 유니코드 이스케이프 시퀀스

\x0041 = "A"

참고

1. 컴파일 타임에 약어 문자열은 동일한 이스케이프 시퀀스를 갖는 보통 문자열로 변환 됩니다.

2. 디버거 조사식 창에서 보면 다음으로 나타납니다. 예) @"C:\files.txt" -> "C:\\files.txt"



형식 문자열


1. 형식 문자열은 런타임에 동적으로 내용을 결정할 수 있는 문자열입니다.

2. static Format 메서드를 사용하고 런타입에 다른 값으로 대체될 내용에 해당하는 자리 표시자를 중괄호로 묶는 방법으로 형식 문자열을 만들 수 있습니다.


class FormatString { static void Main() { // 유저 입력 받음. System.Console.WriteLine("Enter a number"); string input = System.Console.ReadLine(); // 입력 내용을 int 형으로 변환 int j; System.Int32.TryParse(input, out j); // 각 반복에 다른 문자열을 출력 string s; for (int i = 0; i < 10; i++) { // 정렬 포맷 없는 간단한 형식 문자열 s = System.String.Format("{0} times {1} = {2}", i, j, (i * j)); System.Console.WriteLine(s); } // 디버그 모드에서 콘솔 창을 열린 채로 유지 System.Console.ReadKey(); } }


부분 문자열


1. 부분 문자열(substring)은 문자열에 포함된 임의의 문자 시퀀스입니다.

2. Substring 메서드를 사용하면 원래 문자열의 일부를 새 문자열로 만들 수 있습니다.

2. IndexOf 메서드를 사용하면 하나 이상의 부분 문자열 항목을 검색할 수 있습니다.

3. Replace 메서드를 사용하면 지정된 부분 문자열의 모든 항목을 새 문자열로 바꿀 수 있습니다.

4. Substring 메서드와 마찬가지로 replace는 실제로 새 문자열을 반환하고 원래 문자열을 수정하지 않습니다.


string s3 = "Visual C# Express";
System.Console.WriteLine(s3.Substring(7, 2));
// Output: "C#"

System.Console.WriteLine(s3.Replace("C#", "Basic"));
// Output: "Visual Basic Express"

// Index values are zero-based
int index = s3.IndexOf("C");
// index = 7


개별 문자 액세스


1. 인덱스 값을 이용한 배열 표기법을 사용하여 개별 문자열에 읽기 전용으로 액세스할 수 있습니다.


string s5 = "Printing backwards";

for (int i = 0; i < s5.Length; i++)
{
    System.Console.Write(s5[s5.Length - i - 1]);
}
// Output: "sdrawkcab gnitnirP"


2. StringBuilder 객체를 사용하여 개별 문자를 수정할 수 있습니다.


string question = "hOW DOES mICROSOFT wORD DEAL WITH THE cAPS lOCK KEY?"; System.Text.StringBuilder sb = new System.Text.StringBuilder(question); for (int j = 0; j < sb.Length; j++) { if (System.Char.IsLower(sb[j]) == true) sb[j] = System.Char.ToUpper(sb[j]); else if (System.Char.IsUpper(sb[j]) == true) sb[j] = System.Char.ToLower(sb[j]); } // 새 문자열을 저장 string corrected = sb.ToString(); System.Console.WriteLine(corrected); // Output: How does Microsoft Word deal with the Caps Lock key?


Null 문자열 및 빈 문자열


1. 빈 문자열은 문자가 들어 있지 않은 System.String 개체의 인스턴스입니다.

2. 빈 문자열은 다음과 같이 초기화됩니다.

string s = String.Empty;


3. 이와 반대로 null 문자열은 String.String 객체의 인스턴스를 참조하지 않으며 null 문자열에서 메서드를 호출하려고 하면 NullReferenceException이 발생합니다.

4. 그러나 문자열 연결(concatenation)과 비교 연산에서는 null 문자열을 사용할 수 있습니다.


static void Main() { string str = "hello"; string nullStr = null; string emptyStr = String.Empty; string tempStr = str + nullStr; // 다음 라인의 결과: hello Console.WriteLine(tempStr); bool b = (emptyStr == nullStr); // 다음 라인의 결과: False Console.WriteLine(b); // 다음 라인은 새 빈 문자열을 만듭니다. string newStr = emptyStr + nullStr; // Null 문자열과 빈 문자열은 다르게 작동합니다. // 다음 두 라인은 0을 표시합니다. Console.WriteLine(emptyStr.Length); Console.WriteLine(newStr.Length); // 다음 라인은 NullReferenceException 을 발생시킵니다. //Console.WriteLine(nullStr.Length); // character 문자는 다른 Chars 처럼 표시되고 카운트될 수 있습니다. string s1 = "\x0" + "abc"; string s2 = "abc" + "\x0"; // 다음 라인의 결과: * abc* Console.WriteLine("*" + s1 + "*"); // 다음 라인의 결과: *abc * Console.WriteLine("*" + s2 + "*"); // 다음 라인의 결과: 4 Console.WriteLine(s2.Length); }


빠른 문자열 생성을 위해 StringBuilder 사용


1. .NET의 문자열 작업은 매우최적화되어 있어 대부분의 경우 성능에 영향을 미치지 않습니다.

2. 하지만 수백 번이나 수천 번 이상 실행되는 루프 같은 일부 시나리오에서는 문자열 작업이 성능에 영향을 줄 수 있습니다.

3. StringBuilder 클래스는 프로그램에서 수행할 문자열 조작 작업이 많을 경우 성능을 향상시켜 주는 문자열 버퍼를 만듭니다.

4. 다음 예제는 새 문자열을 만들지 않고 문자열의 내용을 변경합니다.


System.Text.StringBuilder sb = new System.Text.StringBuilder("Rat: the ideal pet");
sb[0] = 'C';
System.Console.WriteLine(sb.ToString());
System.Console.ReadLine();

//결과: Cat: the ideal pet


5. 다음 예제는 StringBuilder 객체를 사용하여 숫자 형식의 집합에서 문자열을 만듭니다.


class TestStringBuilder { static void Main() { System.Text.StringBuilder sb = new System.Text.StringBuilder(); // 0 - 9 로 구성된 문자열을 만듭니다. for (int i = 0; i < 10; i++) { sb.Append(i.ToString()); } System.Console.WriteLine(sb); // 결과 0123456789 // 문자열 한개를 복사합니다. (System.String 으로는 불가능) sb[0] = sb[9]; System.Console.WriteLine(sb); // 결과 9123456789 } }



문자열 내용 수정


1. 문자열은 변경 불가능이므로 문자열 객체를만든 후에 안전하지 않은 코드를 사용하지 않고는 ㅁ ㅜㄴ자열 개체의 값을 수정할 수 없습니다.

2. 하지만 문자열 값을 수정하여 그 결과를 새 문자열 객체에 저장하는 방법은 많습니다.

3. System.String 클래스는 입력 문자열을 처리하여 새 문자열 객체를 반환하는 메서드를 제공합니다.

4. 많은 경우에 새 객체를 원래 문자열을 가지는 변수에 할당할 수 있습니다.

5. System.Text.RegularExpressions.Regex 클래스는 유사한 방식으로 작동하는 추가 메서드를 제공합니다.

6. System.Text.StringBuilder 클래스는 내부에서 수정할 수 있는 문자 버퍼를 제공합니다.

7. StringBuilder.ToString 메서드를 호출하여 버퍼의 현재 내용을 포함하는 새 문자열 객체를 만들 수 있습니다.

8. 다음 예제는 지정된 문자열에서 부분 문자열을 바꾸거나 제거하는 다양한 방법을 보여줍니다.


class ReplaceSubstrings { string searchFor; string replaceWith; static void Main(string[] args) { ReplaceSubstrings app = new ReplaceSubstrings(); string s = "The mountains are behind the clouds today."; // String.Replace 로 하나의 부분 문자열을 다른 문자열로 바꿀 수 있습니다. // 정확한 일치만 지원합니다. s = s.Replace("mountains", "peaks"); Console.WriteLine(s); // 결과: The peaks are behind the clouds today. // 보다 더 유연성을 원한다면 Regex.Replace 사용하라. // "the" 또는 "The" 를 "many" 또는 "Many" 로 교체 // System.Text.RegularExpressions 를 사용 app.searchFor = "the"; // A very simple regular expression. app.replaceWith = "many"; s = Regex.Replace(s, app.searchFor, app.ReplaceMatchCase, RegexOptions.IgnoreCase); Console.WriteLine(s); // 결과: Many peaks are behind many clouds today. // 한개의 문자와 일치하는 모든 것을 다른 문자료 교체 s = s.Replace(' ', '_'); Console.WriteLine(s); // 결과: Many_peaks_are_behind_many_clouds_today. // 문자열의 중간에서 부분 문자열을 제거 string temp = "many_"; int i = s.IndexOf(temp); if (i >= 0) { s = s.Remove(i, temp.Length); } Console.WriteLine(s); // 결과: Many_peaks_are_behind_clouds_today. // 뒤나 앞의 공백 제거 // TrimStart 와 TrimEnd 참조 string s2 = " I'm wider than I need to be. "; // 새 문자열 변수의 결과를 저장 temp = s2.Trim(); Console.WriteLine(temp); // 결과: I'm wider than I need to be. // 디버그에서 콘솔창을 열어논 채로 유지 Console.WriteLine("Press any key to exit"); Console.ReadKey(); } // Regex.Replace 에 의해 호출되는 커스텀 매치 메소드 // System.Text.RegularExpressions 사용 string ReplaceMatchCase(Match m) { // 일치 문자가 대문자인지 검사 if (Char.IsUpper(m.Value[0]) == true) { // 교체 문자를 대문자로 변경 // System.Text 사용 StringBuilder sb = new StringBuilder(replaceWith); sb[0] = (Char.ToUpper(sb[0])); return sb.ToString(); } else { return replaceWith; } } }


9. 배열 표기법을 사용하여 문자열의 개별문자에 액세스하려면 Stringbuilder 객체를 사용합니다.
10. 이 객체를 사용하면 [] 연산자를 오버로드하여 객체의 내부 문자 버퍼에 액세스할 수있습니다.
11. ToCharArray메서드를 사용하면 문자열을 문자 배열로 변환할 수도 있습니다.
12. 다음 예제에서는 ToCharArray를 사용하여 배열을 만든 다음 이 배열의 요소 일부를 수정합니다.
13. 계속해서 매개 변수로 문자 배열을 가지는 문자열 생성자가 호출되어 새 문자열이 만들어집니다.

class ModifyStrings { static void Main() { string str = "The quick brown fox jumped over the fence"; System.Console.WriteLine(str); char[] chars = str.ToCharArray(); int animalIndex = str.IndexOf("fox"); if (animalIndex != -1) { chars[animalIndex++] = 'c'; chars[animalIndex++] = 'a'; chars[animalIndex] = 't'; } string str2 = new string(chars); System.Console.WriteLine(str2); // 디버그 모드에서 콘솔 창을 열린 상태로 유지 System.Console.WriteLine("Press any key to exit."); System.Console.ReadKey(); } } /* 결과: The quick brown fox jumped over the fence The quick brown cat jumped over the fence */


14. 다음 예제에서는 C 스타일의 문자 배열과 유사한 방식으로 안전하지 않은 코드를 사용하여 문자열을 내부적으로 수정해야 하는 매우 드문 경우를 보여줍니다.

15. 이 예제에서는 fixed 키워드를 사용하여 개별  문자에 내부적으로 액세스하는 방법을 보여줍니다.

16. 또한 C# 컴파일러가 내부적으로 문자열을 저장하는 방식 때문에 문자열에 대한 안전하지 않은 작업에서 발생할 수 있는 부작용에 대해서도 설명합니다.

17. 일반적으로 반드시 필요한 경우가 아니라면 이 방법을 사용하새는 안 됩니다.



class UnsafeString { unsafe static void Main(string[] args) { // 컴파일러는 이 문자열들을 같은 위지에 저장합니다. string s1 = "Hello"; string s2 = "Hello"; // 안전하지 않은 코드를 사용하여 한개의 문자열을 바꿉니다. fixed (char* p = s1) { p[0] = 'C'; } // 두 문자열이 변경되었습니다. Console.WriteLine(s1); Console.WriteLine(s2); // 디버그 모드에서 콘솔 창을 열린 채로 유지합니다. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } }


여러 문자열 연결


1. 연결(Concatenation)은 한 문자열을 다른 문자열의 끝에 추가하는 프로세스입니다.

2. + 연산자를 사용하여 문자열 리터럴이나 문자열 상수를 연결하면 컴파일러가 단일 문자열을 생성합니다.

3. 런타임 연결은 발생하지 않습니다.

4. 하지만 문자열 변수는 런타임에만 연결할 수 있습니다.

5. 이 경우 다양한 접근 방식이 성능에 미치는 영향을 이해해야 합니다.

6. 다음 예제에서는 긴 문자열을 더 짧은 문자열로 분할하여 소스 코드의 가독성을 향상시키는 방법을 보여줍니다.

7. 분할된 문자열은 컴파일 타임에 단일 문자열로 연결됩니다.

8. 문자열의 수에 따른 런타임 성능에는 영향이 없습니다.


static void Main() { // 리터럴들의 연결은 런타임이 아니라 컴파일 타임에 수행됩니다. string text = "Historically, the world of data and the world of objects " + "have not been well integrated. Programmers work in C# or Visual Basic " + "and also in SQL or XQuery. On the one side are concepts such as classes, " + "objects, fields, inheritance, and .NET Framework APIs. On the other side " + "are tables, columns, rows, nodes, and separate languages for dealing with " + "them. Data types often require translation between the two worlds; there are " + "different standard functions. Because the object world has no notion of query, a " + "query can only be represented as a string without compile-time type checking or " + "IntelliSense support in the IDE. Transferring data from SQL tables or XML trees to " + "objects in memory is often tedious and error-prone."; Console.WriteLine(text); }


9. 문자열 변수를 연결하려면 + 또는 += 연산자를 사용하거나 String.Concat 또는 String.Format 또는 StringBuilder.Append 메서드를 사용할 수 있습니다.

10. + 연산자는 사용하기 쉽고 가독성을 높여 줍니다.

11. 한 문장에서 + 연산자를 여러개 사용해도 문자열 내용은 한 번만 복사됩니다.

12. 그러나 반복문 등에서 이 연산을 여러 번 반복하면 효율성이 저하될 수도 있습니다. 다음 예제를 참조하세요.


static void Main(string[] args) { // 이 프로그램을 실행하고 커맨드 라인 스트링을 제공하려면 // Visual Studio 에서, Project > Properties > Debug 을 참조하세요. string userName = args[0]; string date = DateTime.Today.ToShortDateString(); // 한번의 결합을 위해서 + 와 += 연산자를 을 사용 string str = "Hello " + userName + ". Today is " + date + "."; System.Console.WriteLine(str); str += " How are you today?"; System.Console.WriteLine(str); // 디버그 모드에서 콘솔 창을 연린 채로 유지합니다. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } // Example output: // Hello Alexander. Today is 1/22/2008. // Hello Alexander. Today is 1/22/2008. How are you today? // Press any key to exit. //


참고

문자열 연결 연산에서 C# 컴파일러는 null 문자열을 빈 문자열과 같은 것으로 처리하지만 원래 null 문자열의 값을 변화하지는 않습니다.


13. 루프에서와 같이 많은 수의 문자열을 연결하는 경우가 아니라면 이 코드의 성능 비용은 그리 크지 않을 것입니다. String.Concat 과 String.Format 메서드도 같습니다.

14. 하지만 성능이 중요한 경우에는 항상 StringBuilder 클래스를 사용하여 문자열을 연결해야 합니다.

15. 다음 코드에서는 + 연산자와 같은 성능 영향이 없는 StringBuilder 클래스의 Append 메서드를 사용하여 문자열을 연결합니다.


class StringBuilderTest
{
    static void Main()
    {
        string text = null;

        // 타이트한 루프에서 연결은 StringBuilder 을 사용
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        for (int i = 0; i < 100; i++)
        {
            sb.AppendLine(i.ToString());
        }
        System.Console.WriteLine(sb.ToString());

        // 디버그 모드에서 콘솔 창을 열린 채로 유지
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}
// Output:
// 0
// 1
// 2
// 3
// 4
// ...
//



문자열 비교


1. 문자열을 비교할 경우 한 문자열이 다른 문자열보다 크거나 작거나 같다는 결과를 얻게 됩니다.

2. 결과를 결정하는 규칙은 서수 비교를 수행하는지, 문화권 구분 비교를 수행하는지에 따라 달라집니다.

3. 언어 규칙을 고려하지 않고 두 문자열 값을 비교하거나 정렬해야 하는 경우 기본 서수 비교를 사용합니다.

4. 기본 서수 비교(System.StringComparison.Ordinal)는 대/소문자를 구분합니다. 예를 들어, "and", "And", "AND"가 서로 다릅니다.

5. 자주 사용하는 변형으로 System.StringComparison.OrdinalIgnoreCase 가 있는데, 이 경우에는 "and", "And", "AND"가 서로 같습니다.

6. System.StringComparison.OrdinalIgnoreCase 는 파일 이름, 경로 이름, 네트워크 경로 및 사용자 컴퓨터의 로캘에 따라 값이 변경되지 않는 기타 문자열을 비교할 때 자주 사용됩니다.

7. 일반적으로 문화권 구분 비교는 최종 사용자가 입력한 문자열을 비교하고 정렬할 때 사용됩니다.

8. 이것은 이러한 문자열의 문자 및 정렬 규칙이 사용자 컴퓨터의 로캘에 따라 달라질 수 있기 때문입니다.

9. 현재 스레드의 문화권에 따라 동일한 문자를 포함하는 문자열도 다르게 정렬될 수 있습니다.


참고

문자열을 비교할 경우 수행하려는 비교 종류를 명시적으로 지정하는 메서드를 사용해야 합니다. 이렇게 하면 코드를 보다 쉽게 읽고 유지 관리할 수 있습니다. 가능한 경우 수행할 비교의 종류를 지정할 수 있도록 StringComparison 열거형 매개 변수를 사용하는 System.String 및 System.Array 클래스의 메서드 오버로드를 사용해야 합니다. 문자열을 비교할 때는 == 및 != 연산자를 사용하지 않는 것이 좋습니다. 또한 String.CompareTo 인스턴스 메서드는 오버로드가 StringComparison을 사용하지 않으므로 사용하지 않는 것이 좋습니다.

// Internal strings that will never be localized.
string root = @"C:\users";
string root2 = @"C:\Users";

// Use the overload of the Equals method that specifies a StringComparison.
// Ordinal is the fastest way to compare two strings.
bool result = root.Equals(root2, StringComparison.Ordinal);

Console.WriteLine("Ordinal comparison: {0} and {1} are {2}", root, root2,
                    result ? "equal." : "not equal.");

// To ignore case means "user" equals "User". This is the same as using
// String.ToUpperInvariant on each string and then performing an ordinal comparison.
result = root.Equals(root2, StringComparison.OrdinalIgnoreCase);
Console.WriteLine("Ordinal ignore case: {0} and {1} are {2}", root, root2,
                     result ? "equal." : "not equal.");

// A static method is also available.
bool areEqual = String.Equals(root, root2, StringComparison.Ordinal);


// String interning. Are these really two distinct objects?
string a = "The computer ate my source code.";
string b = "The computer ate my source code.";

// ReferenceEquals returns true if both objects
// point to the same location in memory.
if (String.ReferenceEquals(a, b))
    Console.WriteLine("a and b are interned.");
else
    Console.WriteLine("a and b are not interned.");

// Use String.Copy method to avoid interning.
string c = String.Copy(a);

if (String.ReferenceEquals(a, c))
    Console.WriteLine("a and c are interned.");
else
    Console.WriteLine("a and c are not interned.");

// Output:
// Ordinal comparison: C:\users and C:\Users are not equal.
// Ordinal ignore case: C:\users and C:\Users are equal.
// a and b are interned.
// a and c are not interned.


10. 다음 예제는 StringComparison 열거형을 사용하는 System.String 메서드를 통해 원하는 방식으로 문자열을 비교하는 방법을 보여줍니다.

11. String.CompareTo 인스턴스 메서드는 해당 오버로드가 StringComparison을 사용하지 않으므로 이 예제에 사용되지 않습니다.


// "They dance in the street."
// Linguistically (in Windows), "ss" is equal to 
// the German essetz: 'ß' character in both en-US and de-DE cultures.
string first = "Sie tanzen in die Straße."; 
string second = "Sie tanzen in die Strasse.";

Console.WriteLine("First sentence is {0}", first);
Console.WriteLine("Second sentence is {0}", second);

// Store CultureInfo for the current culture. Note that the original culture
// can be set and retrieved on the current thread object.
System.Threading.Thread thread = System.Threading.Thread.CurrentThread;
System.Globalization.CultureInfo originalCulture = thread.CurrentCulture;

// Set the culture to en-US.
thread.CurrentCulture = new System.Globalization.CultureInfo("en-US");

// For culture-sensitive comparisons, use the String.Compare 
// overload that takes a StringComparison value.
int i = String.Compare(first, second, StringComparison.CurrentCulture);
Console.WriteLine("Comparing in {0} returns {1}.", originalCulture.Name, i);

// Change the current culture to Deutch-Deutchland.
thread.CurrentCulture = new System.Globalization.CultureInfo("de-DE");
i = String.Compare(first, second, StringComparison.CurrentCulture);
Console.WriteLine("Comparing in {0} returns {1}.", thread.CurrentCulture.Name, i);

// For culture-sensitive string equality, use either StringCompare as above
// or the String.Equals overload that takes a StringComparison value.
thread.CurrentCulture = originalCulture;
bool b = String.Equals(first, second, StringComparison.CurrentCulture);
Console.WriteLine("The two strings {0} equal.", b == true ? "are" : "are not");

/*
 * Output:
    First sentence is Sie tanzen in die Straße.
    Second sentence is Sie tanzen in die Strasse.
    Comparing in en-US returns 0.
    Comparing in de-DE returns 0.
    The two strings are equal.
 */

12. 다음 예제에서는 System.StringComparer 매개 변수를 사용하는 정적 Array 메서드를 통해 문화권 구분 방식으로 배열에서 문자열을 정렬하고 검색하는 방법을 보여줍니다.


    class SortStringArrays
    {
        static void Main()
        {

            string[] lines = new string[]
            {
                @"c:\public\textfile.txt",
                @"c:\public\textFile.TXT",
                @"c:\public\Text.txt",
                @"c:\public\testfile2.txt"
            };

            Console.WriteLine("Non-sorted order:");
            foreach (string s in lines)
            {
                Console.WriteLine("   {0}", s);
            }

            Console.WriteLine("\n\rSorted order:");

            // Specify Ordinal to demonstrate the different behavior.
            Array.Sort(lines, StringComparer.Ordinal);

            foreach (string s in lines)
            {
                Console.WriteLine("   {0}", s);
            }


            string searchString = @"c:\public\TEXTFILE.TXT";
            Console.WriteLine("Binary search for {0}", searchString);
            int result = Array.BinarySearch(lines, searchString, StringComparer.OrdinalIgnoreCase);
            ShowWhere<string>(lines, result);

            //Console.WriteLine("{0} {1}", result > 0 ? "Found" : "Did not find", searchString);

            // Keep the console window open in debug mode.
            System.Console.WriteLine("Press any key to exit.");
            System.Console.ReadKey();
        }

        // Displays where the string was found, or, if not found,
        // where it would have been located.
        private static void ShowWhere<T>(T[] array, int index)
        {
            if (index < 0)
            {
                // If the index is negative, it represents the bitwise
                // complement of the next larger element in the array.
                index = ~index;

                Console.Write("Not found. Sorts between: ");

                if (index == 0)
                    Console.Write("beginning of array and ");
                else
                    Console.Write("{0} and ", array[index - 1]);

                if (index == array.Length)
                    Console.WriteLine("end of array.");
                else
                    Console.WriteLine("{0}.", array[index]);
            }
            else
            {
                Console.WriteLine("Found at index {0}.", index);
            }
        }


    }
    /*
     * Output:
        Non-sorted order:
           c:\public\textfile.txt
           c:\public\textFile.TXT
           c:\public\Text.txt
           c:\public\testfile2.txt

        Sorted order:
           c:\public\Text.txt
           c:\public\testfile2.txt
           c:\public\textFile.TXT
           c:\public\textfile.txt
        Binary search for c:\public\TEXTFILE.TXT
        Found at index 2.
     */


13. System.Collections.Hashtable, System.Collections.GenericDictonary<TKey, TValue> 및 System.Collections.Generic.List<T> 등의 컬렉션 클래스에는 요소나 키의 형식이 string일 경우 System.StringComparer 매개 변수를 사용하는 생성자가 있습니다.

14. 일반적으로 가능한 경우에는 항상 이러한 생성자를 사용하여 Ordinal 또는 OrdinalIgnoreCase를 지정해야 합니다.


String.Split를 사용하여 문자열 구분 분석


1. 다음 코드 예제에서는 String.Split 메서드를 사용하여 문자열을구문 분석하는 방법을 보여줍니다.

2. Split는 대상 문자열의 흥미로운 하위 문자열을 구문 분석하는 문자를나타내는 문자 배열을 입력으로 사용합니다.

3. 함수는 하위 문자열 배열을 반환합니다.

4. 이 예제에서는 공백, 쉼표, 마침표, 콜론 및 탭을 사용하며, 모두 이러한 구분 문자를 포함하는 배열로 Split에 전달됩니다. 대상 문자열 문자의 각 단어는 결과 문자열 배열과 별도로 표시됩니다.


class TestStringSplit
{
    static void Main()
    {
        char[] delimiterChars = { ' ', ',', '.', ':', '\t' };

        string text = "one\ttwo three:four,five six seven";
        System.Console.WriteLine("Original text: '{0}'", text);

        string[] words = text.Split(delimiterChars);
        System.Console.WriteLine("{0} words in text:", words.Length);

        foreach (string s in words)
        {
            System.Console.WriteLine(s);
        }

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}
/* Output:
    Original text: 'one     two three:four,five six seven'
    7 words in text:
    one
    two
    three
    four
    five
    six
    seven
 */


5. 기본적으로 String.Split는 두 구분 문자가 대상 문자열에 연속적으로 표시되는 경우 빈 문자열을 반환합니다.

6. 선택적 StringSplitOptions.RemoveEmptyentries 매개 변수를 전달하여 출력에서 빈 문자열을 모두 제외할 수 있습니다.

7. String.Split는 문자열배열(단일 문자 대신 대상 문자열을 구문 분석하기 위한 구분 기호 역할을하는 문자시퀀스)을 사용할 수 있습니다.


class TestStringSplit
{
    static void Main() 

        char[] separatingChars = { "<<", "..." };
     string text = "one<<two......three<four";
     System.Console.WriteLine("Original text: '{0}'", text);
     string[] words = text.Split(separatingChars, System.StringSplitOptions
.RemoveEmptyEntries );
     System.Console.WriteLine("{0} substrings in text:", words.Length);
     foreach (string s in words)
         System.Console.WriteLine(s);
     }

// Keep the console window open in debug mode.

System.Console.WriteLine("Press any key to exit.");

System.Console.ReadKey();

}

}

/* Output: 

Original text: 'one<<two......three<four' 3 words in text: one two three<four

*/



문자열에서 일치하는 단어의 수 세기 (LINQ)


1. 이 예제에서는 LINQ 쿼리를 사용하여 한 문자열에서 지정한 단어가 나오는 횟수를 세는 방법을 보여줍니다.

2. 횟수를 세개 위해 먼저 Split 메서드를 호출하여 단어 배열을 만듭니다.

3. Split 메서드는 성능 저하가 있습니다.

4. 단어의 횟수만을 세는 경우라면 대신 Matches 또는 IndexOf 메서드를 사용하는 것이 좋습니다.

5. 그러나 성능이 중요한 문제가 아니거나 문장에 대해 다른 쿼리 형식을 수행하기 위해 해당 문장으르 이미 분할한 경우 LINQ를 사용하여 단어나 구가 나오는 횟수를 계산할 수도 있습니다.


class CountWords { static void Main() { string text = @"Historically, the world of data and the world of objects" + @" have not been well integrated. Programmers work in C# or Visual Basic" + @" and also in SQL or XQuery. On the one side are concepts such as classes," + @" objects, fields, inheritance, and .NET Framework APIs. On the other side" + @" are tables, columns, rows, nodes, and separate languages for dealing with" + @" them. Data types often require translation between the two worlds; there are" + @" different standard functions. Because the object world has no notion of query, a" + @" query can only be represented as a string without compile-time type checking or" + @" IntelliSense support in the IDE. Transferring data from SQL tables or XML trees to" + @" objects in memory is often tedious and error-prone."; string searchTerm = "data"; // 문자열을 단어 배열로 변환 string[] source = text.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries); // 쿼리를 만들고 'data'와 'Data'와 를 찾기 위해서 ToLowerInvariant 메서드를 사용합니다. var matchQuery = from word in source where word.ToLowerInvariant() == searchTerm.ToLowerInvariant() select word; // 쿼리를 실행해서 일치하는 단어의 개수를 셉니다. int wordCount = matchQuery.Count(); Console.WriteLine("{0} 개의 일치 일치 \"{1}\" 가 발견됨.", wordCount, searchTerm); // Keep console window open in debug mode Console.WriteLine("Press any key to exit"); Console.ReadKey(); } } /* Output: 3 개의 일치 "data" 가 발견됨

*/





var


1. Visual C# 3.0 부터는 메서드 범위에서 선언된 변수가 암시적(implicit) 형식 var를 가질 수 있습니다.

2. 암시적으로 형식이 지정된 지역 변수는 형식을 직접 지정한 것처럼 강하게 형식이 지정되었지만 컴파일러가 형식을 결정합니다.

3. 다음의 i의 두 선언은 기능면에서 동일합니다.


var i = 10; // 암시적으로 형식이 지정됨

int i = 10; // 명시적으로 형식이 지정됨


4. 다음 예제에서는 두 개의 쿼리 식을 보여줍니다.

5. 첫번째 식에서 var 의 사용은 허용되나 필수는 아닙니다. 왜냐하면 쿼리 결과가 IEnumerable<string>에서 명확하게 시작되기 때문입니다.

6. 두번째 식에서 var는 필수입니다. 왜냐하면 결과가 익명 형식의 컬렉션이고 그 형식의 이름은 컴파일러 자체 이왜에는 액세스할 수 없기 때문입니다.

7. 예제의 foreach 반복 변수 item 은 암시적으로 형식이 지정되어야 합니다.


// 예제 #1: var 는 선택적이다. // select 절이 문자열을 가리키고 있기 때문이다. string[] words = { "apple", "strawberry", "grape", "peach", "banana" }; var wordQuery = from word in words where word[0] == 'g' select word; // 각 요소는 익명 형식이 아니라 문자열이기 때문에 또한 var는 선택적이다. foreach (string s in wordQuery) { Console.WriteLine(s); } // 예제 #2: var 는 필수이다. // 왜냐하면 select 절이 익명 형식을 기리키고 있기 때문이다. var custQuery = from cust in customers where cust.City == "Phoenix" select new { cust.Name, cust.Phone }; // var 는 필수이다. // 왜냐하면 각각의 item이 익명 형식이기 때문이다. foreach (var item in custQuery) { Console.WriteLine("Name={0}, Phone={1}", item.Name, item.Phone); }


'프로그래밍 > C#' 카테고리의 다른 글

C# 키워드 O~S  (0) 2016.05.31
C# 키워드 F~N  (0) 2016.05.21
C# 키워드 A-E  (0) 2016.05.13
연산자 2  (0) 2016.05.10
정리  (0) 2016.04.09
:
Posted by 지훈2
2016. 4. 9. 20:31

정리 프로그래밍/C#2016. 4. 9. 20:31

enum

1. 열겨형 형식

2. 상수 집합

3. 첫 번째 열거자 값은 0이고 1씩 증가

4. public enum Operators { Add, Sub, Multi, Divide }


클래스 생성자

1. 무조건 public 으로 선언

2. 리턴 타입 명시하지 않음

3. 클래스명과 같아야 함.


문자열로 변환

1. 모든 객체는 Tostring() 메소드를 가지고 있다.


private

1. 외부에서 접근 불가, 첫글자에 밑줄(_)을 쳐서 구분하기 쉽게 할것


partial

클래스 등을 두 이상의 소스 파일로 분할 가능.


속성

1. 보호

2. 메서드처럼 코딩 가능

3. get, set

4. 매개변수는 한개만 가능, 'value' 키워드는 속성의 타입과 같아야 함.

5. 쓰기 보호를 위해서 set을 빼면 읽기전용이 됨. 


함수 오버로딩

1. 함수명은 같더라도 매개변수가 다르면 다른 함수로 인식


DateTime

1. DateTime date = new DateTime(2016, 4, 9)

2. DateTime current = DateTime.Now


배열 선언 방법 3가지

사이즈가 지정되는 고정배열

1. int[] numberArray = new int[5];

   numberArray[0] = 1;

   numberArray[0] = 2;

   numberArray[0] = 3;

   numberArray[0] = 4;

   numberArray[0] = 5;

2. int[] numberArray2 = new int[] { 1, 2, 3, 4, 5 };

3. int[] numberArray3 = { 1, 2, 3, 4, 5 };


클래스 배열 선언

1. Customer[] customerArray = new Customer[5];

   customerArray[0] = new Customer("first", "last", new DateTime(2000,1,1));

   customerArray[1] = new Customer("first", "last", new DateTime(2000,1,1));

   customerArray[2] = new Customer("first", "last", new DateTime(2000,1,1));

   customerArray[3] = new Customer("first", "last", new DateTime(2000,1,1));

   customerArray[4] = new Customer("first", "last", new DateTime(2000,1,1));

2. Customer[] customerArray2 =

   {

      new Customer("first", "last", new DateTime(2000,1,1));

      new Customer("first", "last", new DateTime(2000,1,1));

      new Customer("first", "last", new DateTime(2000,1,1));

      new Customer("first", "last", new DateTime(2000,1,1));

      new Customer("first", "last", new DateTime(2000,1,1));

   };


반복문 for

for (int index = 1; index <= 10; index++)

{

sum += index;

}


internal class Customer (기본값)

같은 네임스페이스 안에서만 클래스만 사용


public class Customer

다른 네이스페이스 안에서도 클래스를 사용 가능


ArrayList 형

1. 동적 배열(다른 타입도 가능)

2. 링크드 리스트로 삽입 삭제시 자동으로 처리

3. using System.Collections

4. 자동으로 형변환


ArrayList arrayList = new ArrayList();

arrayList.Add(0);

arrayList.Add(1);

arrayList.Add(2);

arrayList.Add("HI");  // 타입이 달라지면 비효율, 그냥 변수로 처리하는게 나음

arrayList.Add(new Customer());  // 타입이 달라지면 비효율


arrayList.Insert(2, 2) // 2번째에 2를 삽입

arrayList.Remove(2) // 2를 찾아 지움

arrayList.RemoveAt(1) // 1번째 값 지움


int sum = 0;

for (int index = 0; index < arrayList.Count; index++)

{

    int num = (int)arrayList[index];  // 형 변환이 필요 (많으면 많을수록 성능 저하)

    sum += num;

}


List<T>

리스트 클래스, 데이터 타입이 지정된 동적 배열 (일반화 클래스, 제네릭 클래스, 일반화 컬렉션, 제네릭 컬렉션)

T는 데이터 타입을 나타냄


int[] intArray = new int[5];

ArrayList arrayList = new ArrayList();

List<int> intList = new List<int>();


List<int> intList = new List<int>();

int sum2 = 0;

for (int index = 0; index < intList.Count; index++)

{

    int value =intList[index];  // 형 변환이 필요 없음

    sum2 += num;

}


foreach (int value in intList)  // 위 for보다 깔끔하고 효율적.

{

    sum += value;

}


줄바꿈

Environment.NewLine;


virtual

가상 메서드

자식 클래스에서 재정의된 메서드가 존재하면 그걸 호출함


override

자식 클래스에서 재정의 할 때 붙임


public 이나 protected 만 자식클래스에서 사용 가능

private은 불가

자식 생성자가 호출 될 때 부모 생성자의 매개변수가 없은 생성자가 호출됨

base 키워드를 사용해서 매개변수를 적어준다.

부모 클래스의 변수에 자식 클래스의 변수가 대입될 수 있다. 그러면 재정의됨 메서드는 자식 클래스의 메서드가 호출됨.


String.IsNullOrEmpty()

변수가 null 이거나 빈 경우

if (!String.IsNullOrEmpty(prefix))


이스케이프 문자 사용

"{0}\\{1}\\"

@"{0}\{1}\"

path = String.Format(@"{0}\", DateTime.Now.Year)

https://msdn.microsoft.com/ko-kr/library/8kb3ddd4.aspx


try

try { }

catch (Exception ex)

{ }


폴더 관련 함수

using System.IO;

1. 폴더 생성: Directory.CreateDirectory(path)

2. 폴더 확인: Directory.Exists(path)

3. 경로 합침: Path.Combine(path, name)


파일 쓰기

using (StreamWriter writer = new StreamWriter(path, true))  // true는 append 여부
{
     writer.Write(data);
}


확장 메소드

1. 항상 static 클래스에 static 펑션으로 선언되어야 함.

2. 첫번째 인자는 this 키워드에 확장할 타입이 와야 함.

3. 확장 메소드는 아래 화살표가 붙음



'프로그래밍 > C#' 카테고리의 다른 글

C# 키워드 O~S  (0) 2016.05.31
C# 키워드 F~N  (0) 2016.05.21
C# 키워드 A-E  (0) 2016.05.13
연산자 2  (0) 2016.05.10
C# 총정리  (0) 2016.04.19
:
Posted by 지훈2