이벤트 & 제네릭

C#/CLR via 2020. 2. 28. 08:12
반응형

이벤트

 

이벤트 - C# 프로그래밍 가이드

이벤트(C# 프로그래밍 가이드)Events (C# Programming Guide) 이 문서의 내용 --> 클래스 나 개체에서는 특정 상황이 발생할 때 이벤트를 통해 다른 클래스나 개체에 이를 알려줄 수 있습니다.Events enable a class or object to notify other classes or objects when something of interest occurs. 이벤트를 보내거나 발생시키는클래스를 게시자 라고 하며 이벤트를

docs.microsoft.com

더보기

클래스 나 개체에서는 특정 상황이 발생할 때 이벤트를 통해 다른 클래스나 개체에 이를 알려줄 수 있습니다. 이벤트를 보내거나 발생시키는클래스를 게시자 라고 하며 이벤트를 받거나 처리하는클래스를 구독자라고 합니다.

일반적인 C# Windows Forms 또는 웹 애플리케이션, 단추 및 목록 상자 같은 컨트롤에 의해 발생하는 이벤트를 구독합니다. 컨트롤이 게시하는 이벤트를 찾아보고 처리할 이벤트를 선택하려면 Visual C# IDE(통합 개발 환경)를 사용할 수 있습니다. IDE는 빈 이벤트 처리기 메서드 및 이벤트를 구독하기 위한 코드를 자동으로 추가하는 편리한 방법을 제공합니다. 자세한 내용은 이벤트를 구독 및 구독 취소하는 방법을 참조하세요.

이벤트 개요

이벤트에는 다음과 같은 속성이 있습니다.

  • 게시자는 이벤트 발생 시기를 결정합니다. 구독자는 이벤트에 대한 응답으로 수행할 작업을 결정합니다.

  • 한 이벤트에는 여러 구독자가 있을 수 있습니다. 구독자는 여러 게시자의 여러 이벤트를 처리할 수 있습니다.

  • 구독자가 없는 이벤트는 발생하지 않습니다.

  • 이벤트는 일반적으로 그래픽 사용자 인터페이스에서 단추 클릭이나 메뉴 선택 같은 사용자 작업을 표시하는 데 사용됩니다.

  • 이벤트에 여러 구독자가 있는 경우 이벤트 처리기는 이벤트가 발생할 때 동기적으로 호출됩니다. 이벤트를 비동기적으로 호출하려면 동기 메서드를 비동기 방식으로 호출을 참조하세요.

  • .NET Framework 클래스 라이브러리에서 이벤트는 EventHandler 대리자 및 EventArgs 기본 클래스를 기반으로 합니다.

 

Delegate 기반

1.     보통은 필드를 private와 읽을 수만 있는 읽기 전용 속성들을 포함
private readonly string m_A, m_B, m_C
public SetABC(string _A, string _B, string C)
{ m_A = _A; m_B = _B; m_C = _C; }

2.     Public event EventHandler<SetABC> NewABC; 식으로 선언
해당 이벤트에 들어갈 원형 함수 – void methodname(object a, Aargs e);
클래스 원형을 object로 받는 이유
1.
클래스 상속 가능성
2.
자식 클래스 간 유연성

3.     protected virtual void OnABC(Aargs e)
EventHandler<Aargs> tmp = Volatile.Read(ref NewABC);
if(tmp != null) tmp(this, e);
이벤트를 발생시키는 함수는 위처럼 가상함수로 구성(추천)
단 두 번째처럼 임시변수에 이벤트를 저장해야한다
스레드 간 충돌을 방지(이벤트 삭제 시 호출하면 오류 발생)

4.     public void ActABC(string _A, string _B, string _C){
NewABC e = new NewABC(_A, _B, _C);
OnABC(e);}
식으로 구현하여 마무리한다.

5.     += (Add) 이벤트에 메서드를 추가하고, -= (remove) 로 메서드를 제거한다.
만약 IDisposable Dispose 메서드 구현 시 반드시 등록하였던 모든 이벤트로부터 등록을 해지해야한다.

 

제네릭

 

 

제네릭 - C# 프로그래밍 가이드

제네릭(C# 프로그래밍 가이드)Generics (C# Programming Guide) 이 문서의 내용 --> 제네릭에서 .NET Framework에 도입한 형식 매개 변수 개념은 클라이언트 코드에서 클래스 또는 메서드를 선언하고 인스턴스화할 때까지 하나 이상의 형식 사양을 따르는 클래스 및 메서드를 디자인할 수 있도록 합니다.Generics introduce the concept of type parameters to the .NET Framework,

docs.microsoft.com

더보기

제네릭에서 .NET Framework에 도입한 형식 매개 변수 개념은 클라이언트 코드에서 클래스 또는 메서드를 선언하고 인스턴스화할 때까지 하나 이상의 형식 사양을 따르는 클래스 및 메서드를 디자인할 수 있도록 합니다. 예를 들어 제네릭 형식 매개 변수 T를 사용하여 여기에 표시된 것처럼, 다른 클라이언트 코드에서 런타임 캐스팅 또는 boxing 작업에 대한 비용이나 위험을 발생하지 않고 사용할 수 있는 단일 클래스를 작성할 수 있습니다.

C#복사

 

// 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()); } }

제네릭 클래스 및 메서드는 제네릭이 아닌 클래스 및 메서드에서는 결합할 수 없는 방식으로 재사용성, 형식 안전성 및 효율성을 결합합니다. 제네릭은 컬렉션 및 해당 컬렉션에서 작동하는 메서드에서 가장 자주 사용됩니다. System.Collections.Generic 네임스페이스에는 몇 가지 제네릭 기반 컬렉션 클래스가 있습니다. ArrayList와 같은 제네릭이 아닌 컬렉션은 권장되지 않으며 호환성을 위해 유지 관리됩니다. 자세한 내용은 .NET의 제네릭을 참조하세요.

물론, 사용자 지정 제네릭 형식 및 메서드를 만들어 형식이 안전하고 효율적인 일반화된 솔루션 및 디자인 패턴을 직접 제공할 수도 있습니다. 다음 코드 예제에서는 데모용으로 간단한 제네릭 연결된 목록 클래스를 보여 줍니다. 대부분의 경우 직접 만드는 대신 .NET Framework 클래스 라이브러리에서 제공하는 List<T> 클래스를 사용해야 합니다. 형식 매개 변수 T는 일반적으로 구체적인 형식을 사용하여 목록에 저장된 항목의 형식을 나타내는 여러 위치에서 사용되며, 다음과 같은 방법으로 사용됩니다.

  • AddHead 메서드에서 메서드 매개 변수의 형식.
  • 중첩 Node 클래스에서 Data 속성의 반환 형식.
  • 중첩 클래스에서 private 멤버 data의 형식.

T는 중첩된 Node 클래스에 사용할 수 있습니다. GenericList<T>가 GenericList<int>와 같이 구체적인 형식으로 인스턴스화되면 T가 나타날 때마다 int로 바뀝니다.

C#복사

 

// type parameter T in angle brackets public class GenericList<T> { // The nested class is also generic on T. private class Node { // T used in non-generic constructor. public Node(T t) { next = null; data = t; } private Node next; public Node Next { get { return next; } set { next = value; } } // T as private member data type. private T data; // T as return type of property. public T Data { get { return data; } set { data = value; } } } private Node head; // constructor public GenericList() { head = null; } // T as method parameter type: public void AddHead(T t) { Node n = new Node(t); n.Next = head; head = n; } public IEnumerator<T> GetEnumerator() { Node current = head; while (current != null) { yield return current.Data; current = current.Next; } } }

다음 코드 예제에서는 클라이언트 코드에서 제네릭 GenericList<T> 클래스를 사용하여 정수 목록을 만드는 방법을 보여 줍니다. 형식 인수를 변경하기만 하면 다음 코드를 쉽게 수정하여 문자열이나 다른 모든 사용자 지정 형식 목록을 만들 수 있습니다.

C#복사

 

class TestGenericList { static void Main() { // int is the type argument GenericList<int> list = new GenericList<int>(); for (int x = 0; x < 10; x++) { list.AddHead(x); } foreach (int i in list) { System.Console.Write(i + " "); } System.Console.WriteLine("\nDone"); } }

제네릭 개요

  • 제네릭 형식을 사용하여 코드 재사용, 형식 안전성 및 성능을 최대화합니다.
  • 가장 일반적으로 제네릭은 컬렉션 클래스를 만드는 데 사용됩니다.
  • .NET Framework 클래스 라이브러리에는 System.Collections.Generic 네임스페이스에 여러 가지 새로운 제네릭 컬렉션 클래스가 포함됩니다. 이러한 제네릭 컬렉션 클래스는 가능할 때마다 System.Collections 네임스페이스의 ArrayList처럼 클래스 대신 사용되어야 합니다.
  • 사용자 고유의 제네릭 인터페이스, 클래스, 메서드, 이벤트 및 대리자를 만들 수 있습니다.
  • 제네릭 클래스는 특정 데이터 형식의 메서드에 액세스할 수 있도록 제한될 수 있습니다.
  • 제네릭 데이터 형식에 사용되는 형식에 대한 정보는 리플렉션을 사용하여 런타임 시 얻을 수 있습니다.

이점

1.      코드 보호 – C++(Template)와 다른 점은 제네릭은 소스코드가 없어도 구동이 될 수 있다.

2.      안정 호환이 되지 않으면 컴파일 or 실행 시점에서 오류 발생으로 프로그램을 막는다.

3.      코드 정리 컴파일러가 타입 안정성을 강력히 검사 -> 캐스팅이 거의 필요하지 않다.

4.      성능 기존 값 형태를 object와 함께 다루려면 gc와 박싱 과정이 절실하다. 제네릭은 값 그 자체로 전달할 수 있기에 CLR에서 캐스팅 및 박싱이 발생하지 않는다.

+ GC 측정하기
int cnt = GC.CollectionCount(0);
string text = Stopwatch.StartNew();

열린 타입(Open Type)_
제네릭 타입 매개변수가 등장하는 타입.
CLR
이 해당 변수에 대해 인스턴스 생성 허용 X – 무슨 형인지 아직 모름

닫힌 타입(Closed Type)
일반 매개변수
CLR
이 해당 변수에 대해 인스턴스 생성 허용 O – 무슨 형인지 안다.

 

코드 폭증(Code Explosion)

CLR은 제네릭을 기존 템플릿과 같게 한다면 반드시 그 네이티브 코드를 모두 작성해 두어야한다. 하지만 이는 성능에 치명적이 악영향을 끼친다.

대처_
제네릭 사용 시 같은 형에 대해서는 단 한 번만 컴파일 한다.
참조 형일 경우 모두 동등한 타입으로 분류하여 그 코드를 공유한다.
(
단 값일 경우는 반드시 코드를 작성해야 한다. 포인터와 달리 그 크기가 다 다르기 때문)

 

성질

고정(Invariant)_
Func<T>() ->
일반적인 사용

반공변성(Contra-Variant)
Func<in T>() ->
입력 용도로 사용

공변성(Covariant)
Func<out T>() ->
반환 용도로 사용

ref, out은 매개변수 사용 불가하다

T temp = default(T);
식으로 default 키워드를 사용해 템플릿에 null 대신 초기화를 할 수 있다.

If(obj == null)
값 타입이 아닐 경우 해당 식은 작동한다.

If(o1 == o2)
식은 안 된다.

If(o1 < o2), o1++, o2 += o1
식도 역시 안 된다.

밑 두 개의 경우는 리플렉션과 연산자 오버로딩을 통하여 극복이 가능하긴 하지만 실용성에선 많이 떨어진다.

반응형

'C# > CLR via' 카테고리의 다른 글

문자 문자열 텍스트  (0) 2020.03.25
인터페이스  (0) 2020.03.25
매개변수 & 프로퍼티  (0) 2020.02.21
메서드  (0) 2020.02.19
참조 타입과 값 타입  (0) 2020.02.18
Posted by Lotus' Library
,