2. HugeFlow Study Season 1
Standard Query Operators
• Microsoft .NET Framework 4 에서는 52개의
Standard Query Operator가 있습니다.
• Using 문에 System.Linq 를 추가하면 이 모든
Query Operator들을 사용할 수 있습니다.
• .NET Framework 4에서 사용가능한 Operator들의
목록은 122 Page에 정리되어 있습니다.
3. HugeFlow Study Season 1
Aggregation Operators(1)
• 각 element에 Aggregator 함수를 적용해서 누적계
산을 합니다.
• 이 계산된 결과는 다른 타입이 될 수도 있으며 누적
계산된 결과에 다른 계산을 추가할 수 있습니다.
4. HugeFlow Study Season 1
Aggregation Operator(2)
var nums = Enumerable.Range(1, 3);
var sum = nums.Aggregate(
0,
(acc, i) => acc + i,
acc => acc + 100
);
Console.WriteLine("Sum plus 100 = {0}", sum);
5. HugeFlow Study Season 1
Average, Max, Min and Sum Operator
var nums = Enumerable.Range(5, 50);
var avg = nums.Average();
var max = nums.Max();
var min = nums.Min();
var sum = nums.Sum();
6. HugeFlow Study Season 1
Aggregate 연산자의 활용
List<CallLog> callLog = CallLog.SampleData();
var q = from call in callLog
where call.Incoming == true
group call by call.Number into g
select new
{
Number = g.Key,
Count = g.Count(),
Avg = g.Average(c => c.Duration),
Total = g.Sum(c => c.Duration)
};
7. HugeFlow Study Season 1
LINQ to Object에 내장된 함수들의 퍼포먼스
최적화 하는 법
• http://blogs.msdn.com/csharpfaq/archive/2009/01/26/does-the-linq-to-objects-
provider-have-built-in-performance-optimization.aspx
• LINQ의 퍼포먼스 최적화의 비법은 바로 지연실행!!!
• 만약 하나 이상의 where문을 바로 뒤따르는 하나이상의 Select문에 쿼리는 중간
에 IEnumerable또는 IEnumerable<T>를 생성하지 않고 하나만 만듭니다.
• 만약 쿼리에서 배열 또는 list는 IEnumerable 또는 IEnumerable<T>인터페이스로
부터 foreach loop 를 사용하지 않습니다. 대신에 간단한 for loop로 배열 또는 list
의 길이에 behind에서 elements들에 대해 바로 접근이 가능합니다.
8. HugeFlow Study Season 1
LINQ method Optimization
Cast 만약 데이터소스가 주어진 T타입으로
IEnumerable로 구현되어 있다면 Data가 반환
될 때 Data를 cast하지 않고 반환합니다.
Contains 만약 데이터소스가 ICollection또는
ICollection<T>를 구현하면 해당 매서드의 인
Count 터페이스를 사용합니다.
ElementAt
만약 데이터소스가 IList 또는 IList<T>를 구현
ElementAtOrDefault 하면 그 인터페이스의 Count 매서드와
indexing 연산자를 사용합니다.
Frist
FristOrDefault
Last
LastOrDefault
Single
SingleOrDefault
10. HugeFlow Study Season 1
Cast
Cast는 .NET Framework 2.0 이전의 .NET Framework 1.0 때 스타일의 콜렉션 예를 들면 ArrayList와 같은
컬렉션들을 위해 제공됩니다.
ArrayList list = new ArrayList();
list.Add(1);
list.Add(2);
list.Add(3);
var avg = (from i in list.Cast<int>()
where i < 3
select i).Average();
11. HugeFlow Study Season 1
OfType
OfType Operator Filters는 IEnuemerable Collection의 각 객체들을 오로지 지정된 타입의
IEnumerable<T>로 반환합니다. Cast와 비슷한 동작을 하지만 가장 큰 차이는 OfType은
element를 지정된 Type으로 cast 할 수 없을 경우 값을 제외시키지만 Cast는 Exception을 던집
니다.
ArrayList list = new ArrayList();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add("One");
list.Add("Two");
list.Add("Three");
var avg = (from i in list.OfType<int>()
where i < 3
select i).Average();
12. HugeFlow Study Season 1
ToDictionary
public void ToDictionary()
{
List<Contact> contacts = Contact.SampleData();
Dictionary<string, Contact> conDictionary = contacts.ToDictionary<Contact, string>(c => c.LastName
+ c.FirstName);
Contact record = conDictionary["Kamph" + "Mack"];
Console.WriteLine("Kamph DOB = {0}", record.DateOfBirth);
}
13. HugeFlow Study Season 1
ToList
IEnumerable<int> data = Enumerable.Range(1, 5);
List<int> q = (from i in data
where i < 3
select i).ToList();
q.ForEach(j => Console.WriteLine(j));
14. HugeFlow Study Season 1
ToLookup
var contacts = Contact.SampleData();
var calls = CallLog.SampleData();
var calls_lookup = (from c in calls
orderby c.When descending
select c).ToLookup(c => c.Number);
var q3 = from c in contacts
orderby c.LastName
select new
{
LastName = c.LastName,
Calls = calls_lookup[c.Phone]
};
foreach (var contact in q3)
{
Console.WriteLine("Last name : {0}", contact.LastName);
foreach (var call in contact.Calls)
{
Console.WriteLine(" - {0} call on {1} for {2} min. ", call.Incoming ?
"Incoming" : "Outgoing", call.When, call.Duration);
}
}
15. HugeFlow Study Season 1
ToLookup 과 ToDictionary의 차이점
• ToDictionary는 하나의 키에 단일 값에 매핑하는 반
면 Lookup은 키를 컬렉션에 매핑한다는 점이 다릅
니다.
• Lookup<TKey, TElement>의 새 인스턴스를 만드는
공용 생성자는 없습니다. 또한 Lookup<TKey,
TElement> 개체는 변경할 수 없으므로
Lookup<TKey, TElement> 개체를 만든 후에는 요
소 또는 키를 추가하거나 제거할 수 없습니다.
16. HugeFlow Study Season 1
Default 키워드
• 제네릭 타입인 T의 변수인 경우 T가 참조타입일 경
우 null을 할당하고 구조체가 아닌 숫자 값인 경우
에 0을 할당하는 키워드 입니다.
17. HugeFlow Study Season 1
Element Operators
• DefaultIfEmpty
• ElementAt and ElementAtOrDefault
• First and FirstOrDefault
• Last and LastOrDefault
• Single and SingOrDefault
18. HugeFlow Study Season 1
DefaultIfEmpty
지정된 시퀀스(배열)의 요소를 반환하다가 시퀀스가 비어있으면 형식의 기본값을 반환합니다.
var nums = new[] { 1, 2, 3, 4, 5 };
var empty = new int[] { };
Console.WriteLine("nums.DefaultIfEmpty() = {0}", nums.DefaultIfEmpty());
Console.WriteLine("empty.DefaultIfEmpty() = {0}", empty.DefaultIfEmpty().First());
Console.WriteLine("nums.DefaultIfEmpty(100) = {0}", empty.DefaultIfEmpty(100).First());
19. HugeFlow Study Season 1
Single and SingleOrDefault
시퀀스에서 조건에 맞는 하나의 요소를 반환하고, 시퀀스에 요소가 하나이상 들어있
으면 예외를 Thorw 합니다.
var single = new int[] { 5 };
var nums = new int[] { 1, 2, 3, 4, 5 };
var empty = new int[] { };
var five = single.Single();
var third = nums.Single(i => i == 3);
var no_error = empty.SingleOrDefault();
var no_error2 = empty.SingleOrDefault(i => i == 10);
Console.WriteLine("five = {0}, third = {1}", five, third);
Console.WriteLine("no_error = {0}, no_error2 = {1}", no_error, no_error2);
21. HugeFlow Study Season 1
SequenceEqual
두개의 시퀀스의 요소의 값, 순서, 요소들의 개수를 비교해서 모두 같으면 true를 반환합니다.
var n1 = new string[] { "peter", "paul", "mary" };
var n2 = new string[] { "paul", "peter", "mary" };
var n3 = new string[] { "PETER", "PAUL", "MARY" };
bool n1n2 = n1.SequenceEqual(n2);
bool n1n3 = n1.SequenceEqual(n3);
bool n1n3_2 = n1.SequenceEqual(n3, StringComparer.CurrentCultureIgnoreCase);
Console.WriteLine("n1n2 = {0}, n1n3 = {1}, n1n3_2 = {2}", n1n2, n1n3, n1n3_2);
22. HugeFlow Study Season 1
Generation Operators
• Empty Operator
• Range Operator
• Repeat Operator
23. HugeFlow Study Season 1
Empty
• 지정된 타입으로 Null이 아닌 0개의 요소를 갖는 배
열을 생성합니다.
• 이 연산자에 대한 일반적인 사용은 다른 연산자를
테스트 할 경우입니다.
24. HugeFlow Study Season 1
Range
첫번째 절단인자에서 시작하고 두번째 전달인자 개수만큼의 Integer형
식의 시퀀스를 만듭니다.
var years = Enumerable.Range(1900, 5);
25. HugeFlow Study Season 1
Repeat
Repeat은 주어진 개수만큼 data를 복제합니다.
int[] i = Enumerable.Repeat(-1, 10).ToArray();
string[] s = Enumerable.Repeat("No Data", 3).ToArray();
27. HugeFlow Study Season 1
Zip
두 시퀀스를 지정된 selector function에 의거해서 병합합니다.
var letters = new string[] { "A", "B", "C", "D", "E" };
var numbers = new int[] { 1, 2, 3, };
var q = letters.Zip(numbers, (s, i) => s + i.ToString());
foreach (var s in q)
{
Console.WriteLine(s);
}
28. HugeFlow Study Season 1
Partitioning Operators
• Skip
• Take
• SkipWhile
• TakeWhile
29. HugeFlow Study Season 1
Skip and Take
Skip은 지정된 숫자만큼 시퀀스의 요소를 건너띄고 Take는 지정된 개수만큼 시퀀스
의 요소를 반환합니다.
int[] nums = Enumerable.Range(1, 50).ToArray();
int page = 3;
int pageSize = 10;
var q = nums
.Skip((page - 1) * pageSize)
.Take(pageSize);
30. HugeFlow Study Season 1
SkipWhile And TakeWhile
SkipWhile 과 TakeWhile은 predicate함수에 의해서 true값을 반환하는 것들에 대해서만 Skip
과 Take의 동작을 수행합니다.
string sampleString = @"# comment line 1
# comment line2
Data line 1
Data line 2
This line is ignored";
var q = sampleString.Split('n')
.SkipWhile(line => line.StartsWith("#") == true)
.TakeWhile(line => !string.IsNullOrEmpty(line.Trim()) == true);
32. HugeFlow Study Season 1
All
시퀀스의 모든 요소가 주어진 Predicate 함수를 모두 통과했을 경우 True값을 반환하
는 메서드입니다.
var evens = new int[] { 2, 4, 6, 8, 10 };
var odds = new int[] { 1, 3, 5, 7, 9 };
var nums = Enumerable.Range(1, 10);
Console.WriteLine("All even? even: {0}, odds: {1}, nums: {2}",
evens.All(i => i % 2 == 0), odds.All(i => i % 2
== 0), nums.All(i => i % 2 == 0));
33. HugeFlow Study Season 1
Any
• 시퀀스 중에 하나의 요소라도 주어진 Predicate함
수를 통과하거나 하나이상의 요소가 있을 경우
True를 반환합니다.
34. HugeFlow Study Season 1
Contains
• 시퀀스의 요소 중 Contains의 전달인자와 같은 요
소가 존재할 경우 True를 반환합니다.
• List<T>와 같은 Generic 컬렉션에서 Contains를 사용할 경우
Contains를 사용하면 List<T>에 정의된 Contains를 호출하게 되고
Contains<T>를 사용하면 Enumerable에 정의된 Contains를 호출하
게 됩니다.
• 대부분의 경우에는 문제가 없지만 좀 더 확실한 결과를 얻고 싶을 경
우에는 Contains<T> 확장메서드를 호출하는 것이 좋습니다.