C# - 무명메서드 람다식

C# 2021. 7. 23. 12:21
728x90


무명 메서드는 한 번만 사용할 간단하고 짧은 메서드를 만드는 방법

형식은 delegate( [ 매개 변수 목록]) {구현부}


무명 메서드를 매개 변수로 메서드에 전달할 수도 있다.


무명 메서드의 장점

메서드 이름을 부여하지 않으므로 1회용 메서드에 적합

논리를 구현하는 코드를 실제로 사용하는 곳에 작성 가능

무명메서드를 할당할 대리자의 시그니처로부터 유추가 가능해서 무명메서드 선언 시 반환 형식이 필요 없다

무명메서드를 감싸고 있는 외부 메서드의 지역 변수를 참조할 수 있다.

간단한 논리 구현을 위해 매번 명명(이름 부여)된 메서드를 만들 필요가 없다


c# 3.0부터는 더욱 쉽게 무명 메서드를 만들수 있도록 람다식을 도입했다.

형식은 ([매개 변수]) => 식;


람다식을 이용해서 무명메서드를 작성하게 되면 더욱 코드가 간결해 질 수 있다.


c#에서는 클래스를 이용해서 다른 객체에 무엇인가 발생했음을 알릴 수 있는데 이것을 이벤트라고 한다.


게시자가 이벤트를 보내면 구독자가 수신하는 구조다, 이벤트를 처리할때 람다식을 이용할 수 있다.


event 키워드는 클래스 사용자들이 +=, -= 연산자를 이용해서 이벤트를 구독하는 것만 허용함으로써 클래스를 이용하는 사용자가 잘못 할당하거나, 멋대로 이벤트를 발생시키는 것을 제약할 수 있다.

event 키워드를 이용하면 람다식을 할당할 때 =은 사용이 불가능하다.

그래서 대리자에 잘못할당하는 경우를 막을수 있다.


event 키워드를 이용하면 해당 이벤트를 정의하고있는 클래스 내부에서만 접근이 가능하고 외부에선 접근이 불가능 하다.


action 대신 event 에 사용할수 있는 EventHandler를 사용할수 있다.

EventHandler 클래스는 발신자(sender) 개체와 이벤트 인수(e)을 필요로 한다.


함수형 프로그래밍에서 람다식이 갖는 강점으로는

퍼스트 클래스 함수 - 람다식을 매개 변수로 전달하거나, 함수의 반환값 등으로 사용할 수 있다

클로저 - 람다식을 이용하면 함수 외부의 지역변수를 람다식으로 구현한 함수 내에서 값을 지속적으로 유지하게 함으로써 클로저 개념을 적용할 수 있다

728x90
Posted by 정망스
,
728x90

 

대리자는 매개 변수와 반환 형식을 갖는 메서드를 캡슐화 하는 형식.

메서드의 참조를 저장한다는 점에서 C/C++의 함수 포인터와 비슷하다. 

대리자는 참조하는 메서드의 메모리 주소를 가진다.

대리자 형식으로 다음처럼 정의 된다.

[접근 한정자] delegate 반환형식 대리자이름(매개 변수);

public delegate void StudyDelegate(string studyString);

대리자는 아래처럼 같은 형식을 갖는 메서드를 할당 하여 사용 할 수 있다.

public delegate void StudyDelegate(string studyString);

public static void TestDelegate(string TestString)
{
	Console.WriteLine(dateText);
}

StudyDelegate delegate = TestDelegate;

 

하나의 특정 메서드를 대리자 변수에 할당하는 형태의 대리자를 유니캐스트 대리자 라고 부른다.

대리자는 한 개의 대리자 변수를 통해 여러 개의 메서드를 호출할 수 있는데 이런 형태의 대리자를

멀티캐스트 대리자라 부른다.

1. Delegate.Combine(), Delegate.Remove() 메서드를 이용한 멀티캐스트 대리자 사용

private delegate void StudyDelegate(int a);

private state void A(int x) {...};
private state void B(int x) {...};
private state void C(int x) {...};
private state void D(int x) {...};

StudyDelegate aDel = A;
StudyDelegate bDel = B;
StudyDelegate cDel = C;
StudyDelegate dDel = D;

StudyDelegate studydelegate = (StudyDelegate)Delegate.Combine(new StudyDelegate[] {A, B, C, D});

StudyDelegate studydelegate2 = (StudyDelegate)Delegate.Combine(A, B, C, D);

StudyDelegate studydelegate3 = (StudyDelegate)Delegate.Remove(studydelegate, C);

2. +=, -= 연산자를 이용한 멀티캐스트 대리자 사용

private delegate void StudyDelegate(int a);

private state void A(int x) {...};
private state void B(int x) {...};
private state void C(int x) {...};
private state void D(int x) {...};

StudyDelegate aDel = A;
StudyDelegate bDel = B;
StudyDelegate cDel = C;
StudyDelegate dDel = D;

StudyDelegate studydelegate = aDel + bDel;
studydelegate += cDel;
studydelegate += dDel;

studydelegate = studydelegate - dDel;
studydelegate -= cDel;

+=, -=을 이용해 본래 멀티캐스트 대리자에 할당하는 행위는 함수형 프로그래밍의 불변성 개념에 맞지 않다고 한다.

 

대리자는 제네릭 형식을 매개 변수로도 이용할 수 있다.

private delegate T StudyDelegate<T>(T a);

private static int intDel (int x) {...};
private static double doubleDel (double x) {...};

StudyDelegate<int> intDelegate = intDel;
StudyDelegate<double> doubleDelegate = doubleDel;

제네릭 대리자 사용시 제네릭 매개 변수를 다중으로 사용 할 수 있다.

private delegate void StudyDelegate<T1, T2>(T1 a, T2 b);

private static void int_double_Del (int x, double y) {...};

StudyDelegate<int, double> multiDelegate = int_double_Del;

반환값을 갖는 다중 제네릭 대리자도 사용 할 수 있다.

private delegate TResult StudyDelegate<T1, T2, TResult>(T1 a, T2 b);

private static float int_double_Del (int x, double y) 
{
  float result = 1f;
  ...
  return result;
}

StudyDelegate<int, double, float> multiDelegate = int_double_Del;

C# 에서는 void 반환 형식의 내장 대리자인 Action과, 반환 형식을 갖는 Func 내장 대리자를 제공한다.

제공되는 대리자 이름을 대신 사용할 뿐 앞에서 본 반환값이 없는, 그리고 있는 제네릭 대리자와 사용법은 같다.

Action<int, double> delegate1 = int_double_del;
Func<int, double, float> delegate2 = int_double_float_del

 

제네릭 대리자를 이용하면 해당 대리자와 형식이 다른 메서드를 할당할 수 있는데

이것을 대리자에서의 가변성이라고 한다. 대리자의 가변성에는 공변성과 반공변성이 있다.

공변성 : 대리자에서 정의하고 있는 반환 형식보다 하위의 상속 형식 반환을 허용

반공변성 : 할당된 메서드가 대리자에서 정의하고 있는 매개 변수 형식보다 상위 형식의 매개 변수를 취할 수 있다

보고있는 책에서 정리된 내용인데.. 이해가 될려니 말려니.. 말이 너무 어렵다.

내가 이해하기 쉽도록 말을 정리 해보려 노력한다...

부모클래스는 자식을 받아들일수 있으나 자식클래스는 부모를 받아들일수 없다.

(쓰고 보니 참.. 조금 그런 말이다..)

 

기본적인 함수의 형태는 리턴타입 함수이름(인수)의 형태 인데, 여기서 리턴 타입과 인수가 대입이 일어나는 위치로 여기서 공변성반공변성이라는 성질이 발생하는데

선언한 델리게이트의 리턴타입이 부모클래스라면 
자식클래스 및 부모클래스 타입을 리턴 타입으로 가지는 모든 함수를 받아준다. 

리턴타입의 경우는 부모클래스와 자식클래스의 원칙을 그대로 따르므로 공변성을 가진다.

B (class)는 A (class)를 상속받고 있다라는 가정

delegate A aDelegate();

static B bMethod()
{
  B b = null;
  ...
  return b;
}

aDelegate aDel = bMethod;
B b = (B)aDel();

 

하지만 인수는 리턴타입과 반대로 동작하는 반공변성을 가진다.

인수는 델리게이트 객체에 함수를 대입할 때가 아니라 함수를 호출 할 때 대입이 일어나므로 비교 시점이 호출할 때 이다

그래서 호출할 때 델리게이트에 등록되어있는 인수의 타입보다 더 큰, 상위 개념의 인수를 호출할 수도 있는, 공변성과는 반대 되는 (반공변성)이 적용된다.

B (class)는 A (class)를 상속받고 있다라는 가정

delegate void bDelegate(B b);

static void aMethod(A a) {...}

bDelegate bDel = aMethod;
A a = null;

bDel((B)a);
728x90
Posted by 정망스
,
728x90

 

함수형 프로그래밍이란..

함수들의 조합으로 만들어지는 함수형 프로그램에 사용되는 프로그래밍 방식을 말한다.

간단히 설명하면 각 함수들은 인자를 받고 그에 따른 결과만 내놓을 뿐 함수 내부적으로 어떠한 상태도 가지지 않는다.

때문에 함수 내부에서 벌어지는 일에 대해서는 전혀 신경 쓸 필요가 없고, 함수 호출 시 입력하는 값과 그에 따른 결과 값을 제대로 주는지만 중요할 뿐인 방식이다.

함수형 프로그래밍에서는 사용하는 모든 데이터가 변경 불가능이라는 전제를 가지고 있고, 함수 내부에서 예외 상황이 발생할 수 있는 경우나, 로그를 출력하는 부분이 있는것 처럼에 부수적인 부분은 존재하지 않는다.

이런 특징들 덕분에 함수형 프로그래밍은 코드를 테스트하기 쉽고, 함수가 하는 일이 명확하기 때문에 함수의 정의를 좀 더 정확히 할 수 있고 읽기 좋게 할 수 있는 장점을 가지고 있다.

 

 

728x90
Posted by 정망스
,
728x90

LINQ 부분까지 정리해논 ppt 입니다..

 

 

c# 윈도우 프로그래밍 정리.pptx

728x90
Posted by 정망스
,


맨 위로
홈으로 ▲위로 ▼아래로 ♥댓글쓰기 새로고침