Enumerable์ LINQ์คํ์ผ ํ์ฅ๋ฉ์๋๋ฅผ ๋ณด๋ฉด ๋ชฉ๋ก์ ์กฐํํ๊ฑฐ๋ ์ ๋ ฌํ ๋ ๋ชฉ๋ก์ ๋ฐํํ๊ธฐ ์ํด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌํ ๋น ํ์ง ์์ต๋๋ค. ๋น๋ฐ์ yield ํค์๋์ธ๋ฐ์, yield ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด, ๋ชฉ๋ก์ ์๋นํ๋ ์ฝ๋์ ๋ฐํํ๋ ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ ์ ์๋๋ฐ์, ์ฝ๋์์ผ๋ก๋ ๋ถ๋ฆฌ๋์ด ์์ง๋ง, ์ค์ ์ฝ๋ ํ๋ฆ์ ๋๊ฐ์ง ํฌ์ธํธ๊ฐ ๊ฒฐํฉ๋ฉ๋๋ค.
A.B.C.ToList() ํํ๋ก yield๋ก ๋ฐํํ๋ IEnumerable ๋ชฉ๋ก์ ๋ฐํํ๋ ๋ฉ์๋๋ฅผ ๊ฒฐํฉํ๋ฉด, ๋ฉ๋ชจ๋ฆฌ ์ฌํ ๋น ์์ด ์ํ๋ชฉ๋ก์ด yield์ ์ํด ์ฐ์ํ๊ฒ ๊ฒฐํฉํฉ๋๋ค.
IEnumerable๊ณผ yield, ๊ทธ๋ฆฌ๊ณ ๊ฒฐํฉ๊ณผ await foreach๋ฅผ ์ ์ ํ ์ ์ด์ฉํ๋ฉด, ์ํ์ ์ ์ด
๋ฅผ ์ฝ๋๋ก ์ฐ์ํ๊ฒ ์งค ์ ์์ต๋๋ค.
์ด๋ฐ ํน์ง๋ค์ด ํจ์ํ ์ธ์ด์ ์ํฅ์ด๋ผ๊ณ ๊ฐ์ธ์ ์ผ๋ก ์๊ฐํ๊ณ ์๋๋ฐ, ๋ช ํํ๊ฒ ์ด๊ฑฐ๋ค ๋ผ๊ณ ํ ์ ๋๋ก ์ ๋ฆฌ๋ ๋ชปํ์ต๋๋ค. ์๊ฐ ๋ ๋ ์ฝ๋๋ก ํํํ๊ฒ ์ต๋๋ค.
IEnumerable์ Concat ๋ฉ์๋.
๋ชฉ๋ก์ ๊ฒฐํฉ์ ์ค์ ๋ก yield return์ ์ฐ์์
๋๋ค.
public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return ConcatIterator<TSource>(first, second);
}
static IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second) {
foreach (TSource element in first) yield return element;
foreach (TSource element in second) yield return element;
}
delegate๋ฅผ ์ด์ฉํ๋ฉด selector
๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค. Enumerable์ LINQ ๋ฉ์๋๋ฅผ ๋ณด๋ฉด, selector
๋ฅผ Func<TSource, TResult>
ํํ๋ก ์ฌ์ฉํ์์ ์ ์ ์์ต๋๋ค. ์๋ฅผ๋ค์ด,
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) {
if (source == null) throw Error.ArgumentNull("source");
if (selector == null) throw Error.ArgumentNull("selector");
if (source is Iterator<TSource>) return ((Iterator<TSource>)source).Select(selector);
if (source is TSource[]) return new WhereSelectArrayIterator<TSource, TResult>((TSource[])source, null, selector);
if (source is List<TSource>) return new WhereSelectListIterator<TSource, TResult>((List<TSource>)source, null, selector);
return new WhereSelectEnumerableIterator<TSource, TResult>(source, null, selector);
}
์ ๊ฒฝ์ฐ, selector
๋ฅผ ์ ๋ค๋ฆญ๊ณผ ๊ฐ์ด ์ฌ์ฉํด์ Select
๋ฉ์๋์ selector
์ ์ข
์์ฑ์ ์ ๊ฑฐํฉ๋๋ค.
๋ชฉ๋ก์ ๋ฐํ ํ ๋ ๋น ๋ชฉ๋ก์ new List<TItem>()
ํํ๋ก ๊ณง์ ๋ฐํํฉ๋๋ค. ํ์ง๋ง ์ด๋ฌ๋ฉด ๋ฉ์๋๊ฐ ํธ์ถ๋ ๋๋ง๋ค ์ธ์คํด์ค๊ฐ ์์ฑ๋๋ฏ๋ก, Enumerable.Empty<TItem>()
๊ฐ ์ข์ ์ ํ์ผ ์ ์์ต๋๋ค. ๋ด๋ถ์ ์ผ๋ก๋ ํด๋น ํ์
์ ์ ์ ์ผ๋ก ํ ๋นํ์ฌ ์ฌ์ฌ์ฉ ํฉ๋๋ค.
internal class EmptyEnumerable<TElement>
{
public static readonly TElement[] Instance = new TElement[0];
}
LINQ์ ์ต์ํด์ง๋ฉด selector
์ ์ํด ์๋ฃ๋ฅผ ๋ฌถ์๋ค ํ์๋ค ํ ์ ์์ต๋๋ค.
GroupBy
: selector ๊ธฐ์ค์ผ๋ก ๋ฌถ์
SelectMany
: selector ๊ธฐ์ค์ผ๋ก ํ
์)
list = list.GroupBy(x => x.์ฑ๋ณ).SelectMany(x => x.OrderBy(y => y.๋ฑ์).Take(2));
// ๊ฒฐ๊ณผ : ๋จ์์ค ์ฑ์ ์ด ๊ฐ์ฅ ์ข์ 2๋ช
์ ๋ณด, ์ฌ์ ์ค ์ฑ์ ์ด ๊ฐ์ฅ ์ข์ 2๋ช
์ ๋ณด
์ข์ ์ค๋ช ๊ฐ์ฌํฉ๋๋ค