C#의 역사 : https://docs.microsoft.com/ko-kr/dotnet/csharp/whats-new/csharp-version-history
제네릭(Generic) : https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/generics/
제네릭이 C# 언어 및 CLR(공용 언어 런타임)의 버전 2.0에 추가되었습니다. 제네릭은 .NET Framework에 클라이언트 코드에서 클래스 또는 메서드를 선언하고 인스턴스화할 때까지 하나 이상의 형식 사양을 따르는 클래스 및 메서드를 디자인할 수 있도록 만드는 형식 매개 변수 개념을 도입합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // Declare the generic class. public class GenericList<T> { public void Add(T input) { } } class TestGenericList { private class ExampleClass { } static void Main() { // Declare a list of type int. GenericList<int> list1 = new GenericList<int>(); list1.Add(1); // Declare a list of type string. GenericList<string> list2 = new GenericList<string>(); list2.Add(""); // Declare a list of type ExampleClass. GenericList<ExampleClass> list3 = new GenericList<ExampleClass>(); list3.Add(new ExampleClass()); } } | cs |
.NET 클래스 라이브러리의 ArrayList 컬렉션 클래스를 사용하는 간단한 프로그램을 작성하면 제네릭이 아닌 컬렉션 클래스를 사용할 경우의 제한 사항을 보여 줄 수 있습니다. ArrayList 클래스의 인스턴스는 모든 참조 또는 값 형식을 저장할 수 있습니다.
ArrayList에 추가된 모든 참조 형식이나 값 형식이 암시적으로 Object로 업캐스팅됩니다. 캐스팅과 boxing 및 unboxing 작업은 모두 성능을 저하시키므로 큰 컬렉션을 반복해야 하는 시나리오에서는 boxing 및 unboxing이 큰 영향을 줄 수 있습니다. 다른 제한 사항은 컴파일 시간 형식 검사가 없다는 것입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | System.Collections.ArrayList list = new System.Collections.ArrayList(); // Add an integer to the list. list.Add(3); // Add a string to the list. This will compile, but may cause an error later. list.Add("It is raining in Redmond."); int t = 0; // This causes an InvalidCastException to be returned. foreach (int x in list) { t += x; } | cs |
?? 연산자 (null 병합 연산자) : https://docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/operators/null-coalescing-operator
?? 연산자는 null 병합 연산자라고 합니다. 이 연산자는 피연산자가 null이 아닐 경우 왼쪽 피연산자를 반환하고 null일 경우 오른쪽 피연산자를 반환합니다.
nullable 형식 : https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/nullable-types/
기본 형식의 정의되지 않은 값을 표시해야 하는 경우 nullable 형식을 사용합니다.
nullable 형식은 null 값이 할당될 수 있는 값-형식 변수를 나타냅니다.
T? 구문은 Nullable<T>의 축약형입니다.
Nullable<T>.HasValue 및 Nullable<T>.Value 읽기 전용 속성을 사용하여 null인지 테스트하고 값을 검색합니다.
- HasValue 속성은 변수에 값이 있으면 true를 반환하고, null이면 false를 반환합니다.
- Value 속성은 HasValue가 true를 반환하는 경우 값을 반환합니다. 그렇지 않으면 InvalidOperationException이 throw됩니다.
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 | class NullCoalesce { static int? GetNullableInt() { return null; } static string GetStringValue() { return null; } static void Main() { //Nullable<int> x = null; int? x = null; // x의 값이 null이 아닌 경우, y는 x값을 가진다. null인 경우 -1을 지정 // if ( x == null ) { y = -1; } else { y = x; } int y = x ?? -1; // 메소드의 결과가 null인 경우 default(int)를 가지고, // null이 아닌 경우 메소드의 결과 i 값으로 int i = GetNullableInt() ?? default(int); string s = GetStringValue(); // s의 값을 출력, s의 값이 null인 경우 "Unspecified"를 출력 // 이 예제에서는 "Unspecified"가 출력 Console.WriteLine(s ?? "Unspecified"); } } | cs |
default 키워드(기본값 식) : https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/statements-expressions-operators/default-value-expressions
기본값 식은 특히 제네릭 클래스와 메서드에서 유용합니다. 제네릭 사용으로 발생하는 한 가지 문제는 다음과 같은 내용을 미리 알지 못하는 경우 매개 변수가 있는 형식 T에 기본값을 할당하는 방법입니다.
- T가 참조 형식인지 값 형식인지 여부
- T이 값 형식인 경우 숫자 값인지 구조체인지 여부를 표시합니다.
매개 변수가 있는 형식 T의 변수 t가 제공되었을 때 t = null 문은 T가 참조 형식인 경우에만 유효합니다. 할당 t = 0은 숫자 값 형식에만 작동하고 구조체에는 작동하지 않습니다. 이를 해결하려면 기본값 식을 사용합니다.
1 2 3 4 5 6 7 | T t = default(T); // 제네릭 클래스와 메서드 이외에도 사용이 가능 var s = default(string); var d = default(dynamic); var i = default(int); var n = default(int?); // n is a Nullable int where HasValue is false. | cs |
yield return/break(반복기) : https://docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/keywords/yield, https://docs.microsoft.com/ko-kr/dotnet/csharp/iterators
yield return 문을 사용하여 각 요소를 따로따로 반환할 수 있습니다.
yield break 문을 사용하여 반복기를 종료할 수 있습니다.
foreach 문 또는 LINQ 쿼리를 이용하여 반복기 메서드를 사용합니다. 각각의 foreach 루프의 반복이 반복기 메서드를 호출합니다. yield return 문이 반복기 메서드에 도달하면 expression 이 반환되고 코드에서 현재 위치는 유지됩니다. 다음에 반복기 함수가 호출되면 해당 위치에서 실행이 다시 시작됩니다.
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.Collections.Generic; public class PowersOf2 { static void Main() { // 2의 8승까지 출력한다. foreach (int i in Power(2, 8)) { Console.Write("{0} ", i); } } public static IEnumerable<int> Power(int number, int exponent) { int result = 1; for (int i = 0; i < exponent; i++) { result = result * number; yield return result; } } // 출력결과: 2 4 8 16 32 64 128 256 } | cs |
Partial 클래스 : https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods
클래스, 구조체, 인터페이스 또는 메서드의 정의를 둘 이상의 소스 파일에 분할할 수 있습니다. 각 소스 파일에는 형식 또는 메서드 정의 섹션이 있으며 모든 부분은 응용 프로그램이 컴파일될 때 결합됩니다.
(C# 3.0에서 partial 메소드가 추가됨)
1 2 3 4 5 6 7 8 9 10 11 | public partial class Employee { public void DoWork() { } } public partial class Employee { public void GoToLunch() { } } | cs |
이름이 없는 메서드로 델리게이트에 전달되는 메소드가 일회성으로만 필요할 때 편의상 사용된다.
무명 메서드를 사용하면 별도 메서드를 만들 필요가 없기 때문에 대리자를 인스턴스화하는 코딩 오버헤드가 줄어듭니다.
1 2 3 4 | // Create a delegate. delegate void Del(int x); // Instantiate the delegate using an anonymous method. Del d = delegate(int k) { /* ... */ }; | cs |
1 2 3 | // Create a handler for a click event. button1.Click += delegate(System.Object o, System.EventArgs e) { System.Windows.Forms.MessageBox.Show("Click!"); }; | cs |
메서드를 만드는 것이 불필요한 오버헤드처럼 보일 수도 있는 경우 대리자 대신 코드 블록을 지정하는 것이 유용할 수 있습니다. 좋은 예로 새 스레드를 시작하는 경우를 들 수 있습니다. 이 클래스는 스레드를 만들며, 대리자에 대한 추가 메서드를 만들지 않고 스레드에서 실행하는 코드도 포함합니다.
1 2 3 4 5 6 7 8 | void StartThread() { System.Threading.Thread t1 = new System.Threading.Thread ( delegate() { System.Console.Write("Hello, "); System.Console.WriteLine("World!"); }); t1.Start(); } | cs |
정적 클래스는 기본적으로 비정적 클래스와 동일하지만, 정적 클래스는 인스턴스화할 수 없다는 한 가지 차이점이 있습니다. 즉, new 키워드를 사용하여 클래스 형식의 변수를 만들 수 없습니다. 인스턴스 변수가 없기 때문에 클래스 이름 자체를 사용하여 정적 클래스의 멤버에 액세스합니다.
※ 자체 인스턴스 하나만 생성될 수 있도록 하는 비정적 클래스를 만들려면 C#에서 Singleton 키워드로 구현을 참조하세요.
'Part 3 > ¶ C#(C sharp)' 카테고리의 다른 글
UI 접근 (0) | 2020.03.15 |
---|---|
Event 처리 (0) | 2020.03.08 |
C# 버전 특징 (0) | 2018.09.14 |