|
|
## 이벤트
|
|
|
## **Delegate**
|
|
|
**Delegate**는 Method를 참조하는 형식이다. **Delegate**에 매개변수와 반환 형식을 정의하고, 이와 같은 구성의 Method를 할당하여 대신 호출해 주는 역할을 한다.
|
|
|
|
|
|
## Delegate
|
|
|
```
|
|
|
delegate int Calculate(int x, int y);
|
|
|
```
|
|
|
```
|
|
|
class Mathematics
|
|
|
{
|
|
|
public int Add(int x, int y)
|
|
|
{
|
|
|
return x + y;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
Mathematics math = new Mathematics();
|
|
|
Calculate calculate = math.Add; // new Calculate(math.Add);
|
|
|
|
|
|
## Lambda
|
|
|
int result = calculate(2, 3);
|
|
|
|
|
|
## LINQ |
|
|
Console.WriteLine(result); // 출력 결과 : 5
|
|
|
```
|
|
|
|
|
|
#### **Delegate Chain**
|
|
|
`+=` 연산자를 사용해서 같은 형태의 여러 Method를 참조하여 동시에 호출할 수 있다. 반대로 `-=` 연산자를 사용해서 참조를 해제할 수도 있다.
|
|
|
|
|
|
```
|
|
|
delegate void MyDelegate();
|
|
|
```
|
|
|
```
|
|
|
class MyClass
|
|
|
{
|
|
|
public void funcFirst()
|
|
|
{
|
|
|
Console.WriteLine("First Function");
|
|
|
}
|
|
|
|
|
|
public void funcSecond()
|
|
|
{
|
|
|
Console.WriteLine("Second Function");
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
MyClass myClass = new MyClass();
|
|
|
|
|
|
MyDelegate myDelegate = myClass.funcFirst;
|
|
|
myDelegate += myClass.funcSecond; // '+=' 연산자 사용
|
|
|
|
|
|
myDelegate();
|
|
|
|
|
|
// 출력 결과 :
|
|
|
// First Function
|
|
|
// Second Function
|
|
|
```
|
|
|
|
|
|
## **Event**
|
|
|
**Event**는 **Delegate**와 마찬가지로 Method를 참조하는 형식이다. 클래스 내의 특정 Event가 일어났음을 외부에 알려주는 기능을 한다. **Event**에 Method를 추가/제거하여 실행될 명령들을 지정할 수 있다. **Event**는 **Delegate**와 달리 **인터페이스**에서 선언할 수 있는 특징이 있다.
|
|
|
|
|
|
```
|
|
|
delegate void EventHandler(int x);
|
|
|
```
|
|
|
```
|
|
|
class Mathematics
|
|
|
{
|
|
|
public event EventHandler CheckNumber;
|
|
|
|
|
|
public void excute(int x)
|
|
|
{
|
|
|
if (CheckNumber != null)
|
|
|
{
|
|
|
CheckNumber(x);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
static void EvenNumber(int x)
|
|
|
{
|
|
|
if (x % 2 == 0)
|
|
|
{
|
|
|
Console.WriteLine("Even Number");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void PositiveNumber(int x)
|
|
|
{
|
|
|
if (x > 0)
|
|
|
{
|
|
|
Console.WriteLine("Posotive Number");
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
Mathematics math = new Mathematics();
|
|
|
|
|
|
math.CheckNumber += EvenNumber;
|
|
|
math.CheckNumber += PositiveNumber;
|
|
|
|
|
|
math.excute(3);
|
|
|
// 출력 결과 :
|
|
|
// Even Number
|
|
|
// Posotive Number
|
|
|
|
|
|
math.excute(2);
|
|
|
// 출력 결과 : Posotive Number
|
|
|
```
|
|
|
|
|
|
## **Lambda**
|
|
|
**Lambda**는 **Delegate**보다 더 간편하게 **Anonymous Method**를 정의할 수 있는 표현식이다.
|
|
|
|
|
|
```
|
|
|
delegate int Calculate(int x, int y);
|
|
|
```
|
|
|
```
|
|
|
Calculate calculate = (x, y) =>
|
|
|
{
|
|
|
return x + y;
|
|
|
};
|
|
|
|
|
|
int result = calculate(2, 3);
|
|
|
|
|
|
Console.WriteLine(result); // 출력 결과 : 5
|
|
|
```
|
|
|
|
|
|
* 값을 바로 반환할 수 있으면 **return 문**과 중괄호를 생략할 수 있다.
|
|
|
|
|
|
```
|
|
|
Calculate calculate = (x, y) => x + y;
|
|
|
|
|
|
int result = calculate(2, 3);
|
|
|
|
|
|
System.Console.WriteLine(result); // 출력 결과 : 5
|
|
|
```
|
|
|
|
|
|
* **Lambda**를 사용해서 **Event**를 구현할 수 있다.
|
|
|
|
|
|
```
|
|
|
delegate void EventHandler(int x);
|
|
|
```
|
|
|
```
|
|
|
class Mathematics
|
|
|
{
|
|
|
public event EventHandler CheckNumber;
|
|
|
|
|
|
public void excute(int x)
|
|
|
{
|
|
|
if (CheckNumber != null)
|
|
|
{
|
|
|
CheckNumber(x);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
Mathematics math = new Mathematics();
|
|
|
|
|
|
math.CheckNumber += (x) =>
|
|
|
{
|
|
|
if (x % 2 == 0)
|
|
|
{
|
|
|
Console.WriteLine("Even Number");
|
|
|
}
|
|
|
};
|
|
|
|
|
|
math.CheckNumber += (x) =>
|
|
|
{
|
|
|
if (x > 0)
|
|
|
{
|
|
|
Console.WriteLine("Posotive Number");
|
|
|
}
|
|
|
};
|
|
|
|
|
|
math.excute(3);
|
|
|
// 출력 결과 :
|
|
|
// Even Number
|
|
|
// Posotive Number
|
|
|
|
|
|
math.excute(2);
|
|
|
// 출력 결과 : Posotive Number
|
|
|
```
|
|
|
|
|
|
### **Action, Func**
|
|
|
#### **Action**
|
|
|
**Action**은 반환 값이 없는 **Deletegate**이다. `T`에는 매개변수의 형식을 지정한다.
|
|
|
|
|
|
```
|
|
|
Action
|
|
|
Action <T1>
|
|
|
Action <T1, T2>
|
|
|
…
|
|
|
Action <T1, T2, …, T16>
|
|
|
```
|
|
|
```
|
|
|
Action<int, int> birthday = (month, day) =>
|
|
|
{
|
|
|
DateTime date = new DateTime(DateTime.Now.Year, month, day);
|
|
|
Console.WriteLine(date.ToString("yyyy년 MM월 dd일");
|
|
|
};
|
|
|
|
|
|
birthday(3, 20); // 출력 결과 : 2015년 03월 20일
|
|
|
```
|
|
|
|
|
|
#### **Func**
|
|
|
**Func**은 반환 값이 있는 **Deletegate**이다. `T`에는 매개변수의 형식, `TResult`에는 반환 형식을 지정한다.
|
|
|
|
|
|
```
|
|
|
Func<TResult>
|
|
|
Func<T1, TResult>
|
|
|
Func<T1, T2, TResult>
|
|
|
…
|
|
|
Func<T1, T2 …, T16, TResult>
|
|
|
```
|
|
|
```
|
|
|
Action<int, int, int> add = (x, y) => x + y;
|
|
|
|
|
|
int result = add(2, 3);
|
|
|
|
|
|
System.Console.WriteLine(result); // 출력 결과 : 5
|
|
|
```
|
|
|
|
|
|
## **확장 Method**
|
|
|
### **FirstOrDefault()**
|
|
|
조건과 일치하는 요소를 검색하여 첫 번째로 나온 값을 반환한다. 단, 값이 없으면 그 형식의 기본값을 반환한다.
|
|
|
|
|
|
```
|
|
|
int[] array = new int[] { 3, -2, 5, 0, 7 };
|
|
|
|
|
|
int result1 = array.FirstOrDefault(item => item < 0);
|
|
|
int result2 = array.FirstOrDefault(item => item > 10);
|
|
|
|
|
|
Console.WriteLine(result1); // 출력 결과 : -2
|
|
|
Console.WriteLine(result2); // 출력 결과 : 0
|
|
|
```
|
|
|
|
|
|
### **Where()**
|
|
|
조건과 일치하는 요소의 값들을 `IEnumerable<T>` 형식으로 반환한다.
|
|
|
|
|
|
|
|
|
```
|
|
|
int[] array = new int[] { 3, -2, 5, 0, 7 };
|
|
|
|
|
|
var result = array.Where(item => item > 0);
|
|
|
|
|
|
foreach(int item in result)
|
|
|
{
|
|
|
Console.Write(item + " ");
|
|
|
}
|
|
|
|
|
|
// 출력 결과 : 3 5 7
|
|
|
```
|
|
|
|
|
|
### **Select()**
|
|
|
지정된 식에 해당하는 값을 `IEnumerable<T>` 형식으로 반환한다.
|
|
|
|
|
|
```
|
|
|
int[] array = new int[] { 3, -2, 5, 0, 7 };
|
|
|
|
|
|
var result = array.Select(item => item * 2);
|
|
|
|
|
|
foreach (int item in result)
|
|
|
{
|
|
|
Console.Write(item + " ");
|
|
|
}
|
|
|
|
|
|
// 출력 결과 : 6 –4 10 0 14
|
|
|
```
|
|
|
|
|
|
## **LINQ**
|
|
|
**LINQ(Language Integrated Query)**는 SQL의 Query를 사용해서 데이터를 조회, 가공할 수 있는 기능이다. **LINQ**는 내부적으로 `IEnumerable<T>`의 **확장 Method**를 표현한 문법이므로, `IEnumerable<T>` 형식이거나 그것을 상속한 객체에서 사용할 수 있다.
|
|
|
|
|
|
> System.Linq
|
|
|
|
|
|
```
|
|
|
class Student
|
|
|
{
|
|
|
public string Name { get; private set; }
|
|
|
public int Year { get; private set; }
|
|
|
public double Grade { get; private set; }
|
|
|
|
|
|
public Student(string name, int year, double grade)
|
|
|
{
|
|
|
Name = name;
|
|
|
Year = year;
|
|
|
Grade = grade;
|
|
|
}
|
|
|
|
|
|
public override string ToString()
|
|
|
{
|
|
|
return String.Format("{0} ({1}학년) : {2} 학점", Name, Year, Grade);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class Lecture
|
|
|
{
|
|
|
public string Name { get; private set; }
|
|
|
public string Subject { get; private set; }
|
|
|
|
|
|
public Lecture(string name, string subject)
|
|
|
{
|
|
|
Name = name;
|
|
|
Subject = subject;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
List<Student> students = new List<Student>
|
|
|
{
|
|
|
new Student("Kim", 3, 4.3),
|
|
|
new Student("Lee", 2, 3.5),
|
|
|
new Student("Park", 4, 3.8),
|
|
|
new Student("Choi", 3, 2.7),
|
|
|
new Student("Jeong", 1, 4.1)
|
|
|
};
|
|
|
|
|
|
List<Lecture> lectures = new List<Lecture>
|
|
|
{
|
|
|
new Lecture("Choi", "Java"),
|
|
|
new Lecture("Kim", "C#"),
|
|
|
new Lecture("Kim", "Network"),
|
|
|
new Lecture("Lee", "Database"),
|
|
|
new Lecture("Park", "C")
|
|
|
};
|
|
|
```
|
|
|
|
|
|
#### **from, select**
|
|
|
* **데이터 전체를 조회하여 객체로 반환**
|
|
|
|
|
|
```
|
|
|
// SELECT * FROM students AS student
|
|
|
|
|
|
var result = from student in students
|
|
|
select student;
|
|
|
|
|
|
foreach (var item in result)
|
|
|
{
|
|
|
Console.WriteLine(item);
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
출력 결과 :
|
|
|
Kim (3학년) : 4.3 학점
|
|
|
Lee (2학년) : 3.5 학점
|
|
|
Park (4학년) : 3.8 학점
|
|
|
Choi (3학년) : 2.7 학점
|
|
|
Jeong (1학년) : 4.1 학점
|
|
|
```
|
|
|
|
|
|
* **데이터의 일부를 조회하여 해당 형식으로 반환**
|
|
|
|
|
|
```
|
|
|
// SELECT * FROM students AS student
|
|
|
|
|
|
var result = from student in students
|
|
|
select student.Name;
|
|
|
|
|
|
foreach (var item in result)
|
|
|
{
|
|
|
Console.WriteLine(item);
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
출력 결과 :
|
|
|
Kim
|
|
|
Lee
|
|
|
Park
|
|
|
Choi
|
|
|
Jeong
|
|
|
```
|
|
|
|
|
|
* **Anonymous Type을 이용해서 새로운 형식으로 반환**
|
|
|
|
|
|
```
|
|
|
// SELECT student.Name FROM students AS student
|
|
|
|
|
|
var result = from student in students
|
|
|
select new { Name = student.Name, Grade = student.Grade };
|
|
|
|
|
|
foreach (var item in result)
|
|
|
{
|
|
|
Console.WriteLine(item);
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
출력 결과 :
|
|
|
{ Name = "Kim", Grade = 4.3 }
|
|
|
{ Name = "Lee", Grade = 3.5 }
|
|
|
{ Name = "Park", Grade = 3.8 }
|
|
|
{ Name = "Choi", Grade = 2.7 }
|
|
|
{ Name = "Jeong", Grade = 4.1 }
|
|
|
```
|
|
|
|
|
|
#### **where**
|
|
|
|
|
|
```
|
|
|
// SELECT * FROM students AS student WHERE student.Year >= 2
|
|
|
|
|
|
var result = from student in students
|
|
|
where student.Year >= 2 // 2학년 이상
|
|
|
select student;
|
|
|
|
|
|
foreach (var item in result)
|
|
|
{
|
|
|
Console.WriteLine(item);
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
출력 결과 :
|
|
|
Kim (3학년) : 4.3 학점
|
|
|
Lee (2학년) : 3.5 학점
|
|
|
Park (4학년) : 3.8 학점
|
|
|
Choi (3학년) : 2.7 학점
|
|
|
|
|
|
```
|
|
|
|
|
|
#### **order by**
|
|
|
* **ascending** : 오름차순 (생략 가능), **descending** : 내림차순
|
|
|
|
|
|
```
|
|
|
// SELECT * FROM students AS student ORDER BY student.Year DESC
|
|
|
|
|
|
var result = from student in students
|
|
|
orderby student.Year descending
|
|
|
select student;
|
|
|
|
|
|
foreach (var item in result)
|
|
|
{
|
|
|
Console.WriteLine(item);
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
출력 결과 :
|
|
|
Park (4학년) : 3.8 학점
|
|
|
Kim (3학년) : 4.3 학점
|
|
|
Choi (3학년) : 2.7 학점
|
|
|
Lee (2학년) : 3.5 학점
|
|
|
Jeong (1학년) : 4.1 학점
|
|
|
```
|
|
|
|
|
|
#### **group by**
|
|
|
* **데이터 전체를 조회하여 객체로 반환**
|
|
|
|
|
|
```
|
|
|
// SELECT * FROM students AS student GROUP BY student.Greade
|
|
|
|
|
|
var result = from student in students
|
|
|
group student by student.Year;
|
|
|
|
|
|
foreach (var group in result)
|
|
|
{
|
|
|
Console.WriteLine(String.Format("[{0}학년]", group.Key));
|
|
|
|
|
|
foreach (var item in group)
|
|
|
{
|
|
|
Console.WriteLine(item);
|
|
|
}
|
|
|
|
|
|
Console.WriteLine();
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
출력 결과 :
|
|
|
[1학년]
|
|
|
Jeong (1학년) : 4.1 학점
|
|
|
|
|
|
[2학년]
|
|
|
Lee (2학년) : 3.5 학점
|
|
|
|
|
|
[3학년]
|
|
|
Kim (3학년) : 4.3 학점
|
|
|
Choi (3학년) : 2.7 학점
|
|
|
|
|
|
[4학년]
|
|
|
Park (4학년) : 3.8 학점
|
|
|
```
|
|
|
|
|
|
* **Anonymous Type을 이용해서 새로운 형식으로 반환**
|
|
|
|
|
|
```
|
|
|
// SELECT student.Name, student.Grade FROM students AS student GROUP BY student.Grade ORDER BY student.Year
|
|
|
|
|
|
var result = from student in students
|
|
|
orderby student.Year // ascending
|
|
|
group new { Name = student.Name, Grade = student.Grade } by student.Year;
|
|
|
|
|
|
foreach (var group in result)
|
|
|
{
|
|
|
Console.WriteLine(String.Format("[{0}학년]", group.Key));
|
|
|
|
|
|
foreach (var item in group)
|
|
|
{
|
|
|
Console.WriteLine(item);
|
|
|
}
|
|
|
|
|
|
Console.WriteLine();
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
출력 결과 :
|
|
|
[1학년]
|
|
|
{ Name = "Jeong", Grade = 4.1 }
|
|
|
|
|
|
[2학년]
|
|
|
{ Name = "Lee", Grade = 3.5 }
|
|
|
|
|
|
[3학년]
|
|
|
{ Name = "Kim", Grade = 4.3 }
|
|
|
{ Name = "Choi", Grade = 2.7 }
|
|
|
|
|
|
[4학년]
|
|
|
{ Name = "Park", Grade = 3.8 }
|
|
|
```
|
|
|
|
|
|
#### **join**
|
|
|
|
|
|
```
|
|
|
// SELECT student.Name, student.Year, lecture.Subject FROM students AS student JOIN lectures AS lecture ON student.Name = lecture.Name
|
|
|
|
|
|
var result = from student in students
|
|
|
join lecture in lectures on student.Name equals lecture.Name
|
|
|
select new { Name = student.Name, Year = student.Year, Subject = lecture.Subject };
|
|
|
|
|
|
foreach (var item in result)
|
|
|
{
|
|
|
Console.WriteLine(item);
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
출력 결과 :
|
|
|
{ Name = "Kim", Year = 3, Subject = "C#" }
|
|
|
{ Name = "Kim", Year = 3, Subject = "Network" }
|
|
|
{ Name = "Lee", Year = 2, Subject = "Database" }
|
|
|
{ Name = "Park", Year = 4, Subject = "C" }
|
|
|
{ Name = "Choi", Year = 3, Subject = "Java" }
|
|
|
```
|
|
|
|
|
|
#### **LINQ 예시 코드 분석**
|
|
|
```
|
|
|
var groupTemp = from data in TxPowerItems
|
|
|
group data by data.Path into newData
|
|
|
orderby newData.Key
|
|
|
select new
|
|
|
{
|
|
|
Key = newData.Key,
|
|
|
Temps = newData.ToList()
|
|
|
};
|
|
|
```
|
|
|
|
|
|
* 조회할 객체인 'TxPoertItems'를 가져와 'data'로 사용한다.
|
|
|
|
|
|
```
|
|
|
from data in TxPowerItems
|
|
|
```
|
|
|
|
|
|
* 'data'를 'Path'로 분류하여 'newData'로 저장한다. 'newData'에는 분류된 'Key'와 해당 데이터들이 저장되어 있다.
|
|
|
|
|
|
```
|
|
|
group data by data.Path into newData
|
|
|
```
|
|
|
|
|
|
* 'newData'의 'Key'를 오름차순(ascending)으로 정렬한다.
|
|
|
|
|
|
```
|
|
|
orderby newData.Key
|
|
|
```
|
|
|
|
|
|
* 'newData'의 'Key'와 데이터를 각각 'Key'와 'Temps'로 저장하여 Anonymous Type의 IEnumerable를 반환하여 'groupTemp'에 저장한다.
|
|
|
|
|
|
```
|
|
|
var groupTemp = (생략)
|
|
|
```
|
|
|
```
|
|
|
select new
|
|
|
{
|
|
|
Key = newData.Key,
|
|
|
Temps = newData.ToList()
|
|
|
};
|
|
|
``` |
|
|
\ No newline at end of file |