|
|
* Delegate
|
|
|
정의, 문법, 체인
|
|
|
|
|
|
# 1. Delegate
|
|
|
__Delegate 정의__
|
|
|
|
|
|
* Event
|
|
|
정의, 사용법
|
|
|
|
|
|
***델리게이트(Delegate)***는 대리자로 해석되며, 메서드를 가리킬 수 있는 타입으로 메서드를 대신 실행해주는 역할을 한다.
|
|
|
`delegate` 예약어를 사용하여 타입을 선언한다.
|
|
|
|
|
|
* 람다식
|
|
|
용도, 용법, 람다식으로 Event를 구현하기
|
|
|
|
|
|
__Delegate 문법__
|
|
|
|
|
|
* 확장 메소드 조사
|
|
|
FirstOrDefault(), SingleOrDefault(), Where(), Select()
|
|
|
|
|
|
// overload 버전 전부다 조사할 필요는 없습니다. 위 메소드의 역할과 간단한 샘플만 조사해주세요.
|
|
|
```csharp
|
|
|
public delegate int CalcDelegate(int x, int y);
|
|
|
// 대상 메서드의 반환 타입 및 매개변수 목록과 일치하는 델리게이트 타입을 정의
|
|
|
```
|
|
|
__Delegate 속성__
|
|
|
|
|
|
- Delegate는 C++의 함수 포인터와 유사하지만 형식이 안전(type-safety)하다.
|
|
|
- Delegate를 통해 메서드를 매개 변수로 전달할 수 있다.
|
|
|
- Delegate를 사용하여 콜백 메서드를 정의할 수 있다.
|
|
|
- 여러 Delegate를 연결할 수 있습니다. 예를 들어 단일 이벤트에 대해 여러 메서드를 호출할 수 있다.
|
|
|
- 메서드와 Delegate 형식이 정확히 일치할 필요는 없다.
|
|
|
|
|
|
형식 안전성(type-safety) : 어떠한 연산이 예측 불가능한 결과는 내지 않는 것.
|
|
|
형식 안전성이 보장되지 않는 언어는 예측 불가능한 결과를 내게 된다.
|
|
|
|
|
|
__Delegate 체인__
|
|
|
|
|
|
Delegate를 여러개 연결해서 사용하는 방식이다.
|
|
|
연결된 Delegate는 내부 리스트에 저장되며 차례대로 호출되고 예외 발생시 중단된다.
|
|
|
|
|
|
```csharp
|
|
|
class Program
|
|
|
{
|
|
|
// Delegate 타입 선언
|
|
|
delegate void ClacDelegate(int x, int y);
|
|
|
|
|
|
static void Add(int x, int y) { Console.WriteLine(x + y); }
|
|
|
static void Subtract(int x, int y) { Console.WriteLine(x - y); }
|
|
|
static void Multiply(int x, int y) { Console.WriteLine(x * y); }
|
|
|
static void Divide(int x, int y) { Console.WriteLine(x / y); }
|
|
|
|
|
|
static void Main(string[] args)
|
|
|
{
|
|
|
ClacDelegate calc = Add;
|
|
|
calc(10, 5); // 15
|
|
|
|
|
|
calc += Subtract;
|
|
|
calc += Multiply;
|
|
|
calc += Divide;
|
|
|
|
|
|
calc(10, 5); // 15 5 50 2
|
|
|
|
|
|
calc -= Subtract;
|
|
|
|
|
|
calc(10, 5); // 15 50 2
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
# 2. Event
|
|
|
__Event 정의__
|
|
|
|
|
|
`event`는 정형화된 콜백 패턴 구현을 위해 사용되는 delegate의 간편 표기법이다.
|
|
|
|
|
|
* LINQ 기본 문법 정리
|
|
|
기존 delegate로도 동일하게 구현할 수 있지만, event 예약어를 사용하면 코드를 줄일 수 있다.
|
|
|
|
|
|
* 아래 코드를 분석해주세요.
|
|
|
또한 event를 이용해 외부 구독자(Subscriber)에 의해 delegate에 새롭게 할당하는 것을 제한하고, 직접적인 delegate 호출을 제한하고 있다.
|
|
|
|
|
|
이는 개발자의 실수를 방지하고, delegate 포함하는 클래스를 통해 delegate를 호출하므로써 외부 클래스가 이벤트를 발생시키는 것을 방지할 수 있다.
|
|
|
|
|
|
__Event 문법__
|
|
|
|
|
|
```csharp
|
|
|
public event EventHandler onChange;
|
|
|
// 클래스의 멤버로 정의.
|
|
|
```
|
|
|
|
|
|
__Event 사용법__
|
|
|
|
|
|
```csharp
|
|
|
delegate void eventDelegate();
|
|
|
|
|
|
class EventTest
|
|
|
{
|
|
|
public event eventDelegate clickEvent;
|
|
|
public void buttonClick() { clickEvent(); }
|
|
|
}
|
|
|
|
|
|
class Program
|
|
|
{
|
|
|
static void Click()
|
|
|
{
|
|
|
Console.WriteLine("클릭");
|
|
|
}
|
|
|
|
|
|
static void Main(string[] args)
|
|
|
{
|
|
|
EventTest eventTest = new EventTest();
|
|
|
eventTest.clickEvent += new eventDelegate(Program.Click);
|
|
|
eventTest.buttonClick();
|
|
|
|
|
|
// 아래 코드는 모두 컴파일 에러
|
|
|
|
|
|
// delegate에 할당되는 것을 제한
|
|
|
// eventTest.clickEvent = new eventDelegate(Program.Click);
|
|
|
|
|
|
// 직접적인 delegate 호출하는것을 제한
|
|
|
// eventTest.clickEvent();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
```
|
|
|
// 멤버 변수
|
|
|
public ObservableCollection<PmPowerItem> TxPowerItems
|
|
|
|
|
|
void LinqTestCode()
|
|
|
{
|
|
|
// 이 부분은
|
|
|
// TxPowerItems 컬렉션을 채우는 코드
|
|
|
// TxPowerItems.Add(pmItem);
|
|
|
|
|
|
// 아래 LINQ 코드를 분석해 보세요
|
|
|
// groupTemp 변수는 어떤 형태의 값이 채워지나요?
|
|
|
|
|
|
var groupTemp = from data in TxPowerItems
|
|
|
group data by data.Path into newData
|
|
|
orderby newData.Key
|
|
|
select new
|
|
|
{
|
|
|
Key = newData.Key,
|
|
|
Temps = newData.ToList()
|
|
|
};
|
|
|
}
|
|
|
|
|
|
// PmPowerItem은 아래와 같이 단순한 ValueObject 입니다.
|
|
|
public class PmPowerItem : ViewModelBase
|
|
|
{
|
|
|
private int _number;
|
|
|
private string _type;
|
|
|
private string _probeId;
|
|
|
private string _path;
|
|
|
private string _hostIp; // DU IP
|
|
|
private string _tid; // 메모
|
|
|
private string _aid;
|
|
|
private string _rxMin;
|
|
|
private string _rxMax;
|
|
|
private string _rxAvg;
|
|
|
private string _txMin;
|
|
|
private string _txMax;
|
|
|
private string _txAvg;
|
|
|
private string _time;
|
|
|
private DateTime _dateTime;
|
|
|
|
|
|
public int Number
|
|
|
{
|
|
|
get { return _number; }
|
|
|
set { _number = value; OnPropertyChanged("Number"); }
|
|
|
}
|
|
|
|
|
|
public string Type
|
|
|
{
|
|
|
get { return _type; }
|
|
|
set { _type = value; OnPropertyChanged("Type"); }
|
|
|
}
|
|
|
|
|
|
public string ProbeId
|
|
|
{
|
|
|
get { return _probeId; }
|
|
|
set { _probeId = value; OnPropertyChanged("ProbeId"); }
|
|
|
}
|
|
|
|
|
|
public string Path
|
|
|
{
|
|
|
get { return _path; }
|
|
|
set { _path = value; OnPropertyChanged("Path"); }
|
|
|
}
|
|
|
|
|
|
public string HostIP // DU IP
|
|
|
{
|
|
|
get { return _hostIp; }
|
|
|
set { _hostIp = value; OnPropertyChanged("HostIP"); }
|
|
|
}
|
|
|
|
|
|
public string TID // 메모
|
|
|
{
|
|
|
get { return _tid; }
|
|
|
set { _tid = value; OnPropertyChanged("TID"); }
|
|
|
}
|
|
|
|
|
|
public string AID
|
|
|
{
|
|
|
get { return _aid; }
|
|
|
set { _aid = value; OnPropertyChanged("AID"); }
|
|
|
}
|
|
|
|
|
|
public string RxMin
|
|
|
{
|
|
|
get { return _rxMin; }
|
|
|
set { _rxMin = value; OnPropertyChanged("RxMin"); }
|
|
|
}
|
|
|
|
|
|
public string RxMax
|
|
|
{
|
|
|
get { return _rxMax; }
|
|
|
set { _rxMax = value; OnPropertyChanged("RxMax"); }
|
|
|
}
|
|
|
|
|
|
public string RxAvg
|
|
|
{
|
|
|
get { return _rxAvg; }
|
|
|
set { _rxAvg = value; OnPropertyChanged("RxAvg"); }
|
|
|
}
|
|
|
|
|
|
public string TxMin
|
|
|
{
|
|
|
get { return _txMin; }
|
|
|
set { _txMin = value; OnPropertyChanged("TxMin"); }
|
|
|
}
|
|
|
|
|
|
public string TxMax
|
|
|
{
|
|
|
get { return _txMax; }
|
|
|
set { _txMax = value; OnPropertyChanged("TxMax"); }
|
|
|
}
|
|
|
|
|
|
public string TxAvg
|
|
|
{
|
|
|
get { return _txAvg; }
|
|
|
set { _txAvg = value; OnPropertyChanged("TxAvg"); }
|
|
|
}
|
|
|
|
|
|
public string Time
|
|
|
{
|
|
|
get { return _time; }
|
|
|
set { _time = value; OnPropertyChanged("Time"); }
|
|
|
}
|
|
|
|
|
|
public DateTime DateTime
|
|
|
{
|
|
|
get { return _dateTime; }
|
|
|
set { _dateTime = value; OnPropertyChanged("DateTime"); }
|
|
|
}
|
|
|
|
|
|
public double? TxMinValue { get; set; }
|
|
|
public double? TxMaxValue { get; set; }
|
|
|
public double? TxAvgValue { get; set; }
|
|
|
public double? RxMinValue { get; set; }
|
|
|
public double? RxMaxValue { get; set; }
|
|
|
public double? RxAvgValue { get; set; }
|
|
|
}
|
|
|
|
|
|
``` |
|
|
\ No newline at end of file |
|
|
|
|
|
# 3. 람다식
|
|
|
***람다 식(Lambda Expression)***은 람다 대수(축약 함수)의 형식을 C#에서 구현한 문법이다.
|
|
|
|
|
|
__람다식 용도__
|
|
|
|
|
|
익명 메서드의 간편 표기와, Expression Tree를 이용한 구문 분석 용도로 사용된다.
|
|
|
|
|
|
__람다식 용법__
|
|
|
|
|
|
```csharp
|
|
|
// 익명 메서드
|
|
|
Thread thread1 = new Thread( delegate (object ojb) { Console.WriteLine("ThreadFunc in anonymous method called!"); });
|
|
|
|
|
|
// 람다 식
|
|
|
Thread thread2 = new Thread( (obj) => { Console.WriteLine("ThreadFunc in anonymous method called!"); });
|
|
|
|
|
|
// 람다 식 약식 표현 (괄호 생략)
|
|
|
Thread thread3 = new Thread( (obj) => Console.WriteLine("ThreadFunc in anonymous method called!") );
|
|
|
|
|
|
// 컬렉션과 람다 식
|
|
|
List<int> list = new List<int> { 3, 1, 4, 5, 2 };
|
|
|
list.ForEach((elem) => { Console.WriteLine(elem + " * 2 == " + (elem * 2)); });
|
|
|
|
|
|
// IEnumerable 타입의 확장 메서드를 이용한 조건 카운팅
|
|
|
int count = list.Count((elem) => elem > 3);
|
|
|
```
|
|
|
|
|
|
__람다식으로 Event를 구현하기__
|
|
|
```csharp
|
|
|
delegate void eventDelegate();
|
|
|
|
|
|
class EventTest
|
|
|
{
|
|
|
public event eventDelegate clickEvent;
|
|
|
|
|
|
public void buttonClick() { clickEvent(); }
|
|
|
}
|
|
|
|
|
|
class Program
|
|
|
{
|
|
|
static void Click()
|
|
|
{
|
|
|
Console.WriteLine("클릭");
|
|
|
}
|
|
|
|
|
|
static void Main(string[] args)
|
|
|
{
|
|
|
EventTest eventTest = new EventTest();
|
|
|
eventTest.clickEvent += () => { Console.WriteLine("클릭"); };
|
|
|
eventTest.buttonClick();
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
# 4. 확장 메소드 조사
|
|
|
|
|
|
__FirstOrDefault()__
|
|
|
|
|
|
조건에 맞는 데이터중 첫번째 행을 반환한다.
|
|
|
NULL 반환에 대한 처리해주어야 한다.
|
|
|
|
|
|
```csharp
|
|
|
List<int> months = new List<int> { };
|
|
|
|
|
|
// Setting the default value to 1 after the query.
|
|
|
int firstMonth1 = months.FirstOrDefault();
|
|
|
if (firstMonth1 == 0)
|
|
|
{
|
|
|
firstMonth1 = 1;
|
|
|
}
|
|
|
Console.WriteLine("The value of the firstMonth1 variable is {0}", firstMonth1);
|
|
|
```
|
|
|
|
|
|
__Where()__
|
|
|
|
|
|
특정 조건을 만족하는 요소를 IEnumerable<T>로 열거형을 반환한다.
|
|
|
|
|
|
```csharp
|
|
|
List<int> list = new List<int> { 3, 1, 4, 5, 2 };
|
|
|
IEnumerable<int> enumList = list.Where((elem) => elem % 2 == 0);
|
|
|
Array.ForEach(enumList.ToArray(), (elem) => { Console.WriteLine(elem); });
|
|
|
```
|
|
|
|
|
|
__Select()__
|
|
|
|
|
|
특정 요소를 IEnumerable<T>로 열거형을 반환한다.
|
|
|
개별 요소를 다른 타입으로 변활할 때 사용할 수 있다.
|
|
|
|
|
|
```csharp
|
|
|
List<int> list = new List<int> { 3, 1, 4, 5, 2 };
|
|
|
IEnumerable<double> enumList = list.Select((elem) => (double)elem);
|
|
|
Array.ForEach(enumList.ToArray(), (elem) => { Console.WriteLine(elem); });
|
|
|
```
|
|
|
|
|
|
#5. LINQ 기본 문법 정리
|
|
|
|
|
|
|
|
|
___Delegate 체인___
|
|
|
http://www.csharpstudy.com/DevNote/Article/15 |
|
|
\ No newline at end of file |