Delegate
Delegate는 Method를 참조하는 형식이다. Delegate에 매개변수와 반환 형식을 정의하고, 이와 같은 구성의 Method를 할당하여 대신 호출해 주는 역할을 한다.
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);
int result = calculate(2, 3);
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
- 분류 값(Key)과 각 요소들의 객체를 Lookup 형식으로 반환
// SELECT * FROM students AS student GROUP BY student.Grade
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()
};
- 조회할 'TxPowerItems' 객체를 'data'로 사용한다. 'data'의 'Path'를 기준으로 분류하여 'newData'를 생성한다.
- 'newData'에는 분류 값인 'Key'와 'Key'에 따른 데이터들이 List로 'Temps'에 저장되어 있다. 또한, 'newData'의 'Key'는 오름차순으로 정렬되어 있다.