C#LINQ需要の進化
20374 ワード
LinqはC#3.0に導入され,C#2.0では集合から条件を満たすレコードをフィルタリングする実装方式が実現される.
BookクラスとBookクラスの集合があると仮定すると,集合から単価が50より大きいBookを調べる必要がある.
1、固定クエリーフィールドの実現方法:
Book.csクラス:
Help.csクラス:
Program.csクラス:
上記のコードでは,Priceクエリセットによる50より大きいレコードが実現されている.しかし、需要が変動し、Titleに従ってクエリーする必要がある場合、上記の実装方法は、Titleによるクエリーを記述する方法を別途行う必要がある.
2、不定クエリーフィールドの実現方式
クエリー条件が最後に返されるのはtrueまたはfalseだけです.新しい定義の方法では、if文にtrueとしてのレコードが返され、セットに追加される限り、クエリー条件が具体的に何であるかを知る必要はありません.
Helper.csクラス:
Program.csクラス:
以上の実装方式は依頼delegateを採用し,C#2.0では匿名の方法も提供され,集合中のクエリ条件をフィルタするコードは以下のように変更できる.
C#3.0でLambda式が提供されると、集合フィルタリングは以下のように実現される.
しかし、このように実現するには毎回クラス名Helperが必要であり、IList自身がこの方法を持っていることを望んでおり、C#3.0は拡張方法を提供している.
3、C#3.0拡張方法の実現方式
5、IEnumberable実現方式
IListはIEnumberableから継承されているため、IEnumberableを拡張することによって実現することができる.
6、汎用拡張クラス
BookクラスとBookクラスの集合があると仮定すると,集合から単価が50より大きいBookを調べる必要がある.
1、固定クエリーフィールドの実現方法:
Book.csクラス:
using System;
using System.Collections.Generic;
using System.Text;
namespace LINQTest
{
public class Book
{
public string Title { get; set; }
public decimal Price { get; set; }
public string Author { get; set; }
public string ISBN { get; set; }
}
}
Help.csクラス:
using System;
using System.Collections.Generic;
using System.Text;
namespace LINQTest
{
public class Helper
{
public static IList<Book> SearchBookByPrice()
{
IList<Book> books = new List<Book> {
new Book{Title="Book1", Author="Author1", ISBN="ISBN1", Price=30},
new Book{Title="Book2", Author="Author2", ISBN="ISBN2", Price=40},
new Book{Title="Book3", Author="Author3", ISBN="ISBN3", Price=50},
new Book{Title="Book4", Author="Author4", ISBN="ISBN4", Price=60}
};
IList<Book> results = new List<Book>();
foreach (Book book in books)
{
if (book.Price >= 50)
{
results.Add(book);
}
}
return results;
}
}
}
Program.csクラス:
using System;
using System.Collections.Generic;
using System.Text;
namespace LINQTest
{
class Program
{
static void Main(string[] args)
{
foreach (Book book in Helper.SearchBookByPrice())
{
Console.WriteLine("{0}-{1}", book.Title, book.Price);
}
}
}
}
上記のコードでは,Priceクエリセットによる50より大きいレコードが実現されている.しかし、需要が変動し、Titleに従ってクエリーする必要がある場合、上記の実装方法は、Titleによるクエリーを記述する方法を別途行う必要がある.
2、不定クエリーフィールドの実現方式
クエリー条件が最後に返されるのはtrueまたはfalseだけです.新しい定義の方法では、if文にtrueとしてのレコードが返され、セットに追加される限り、クエリー条件が具体的に何であるかを知る必要はありません.
Helper.csクラス:
using System;
using System.Collections.Generic;
using System.Text;
namespace LINQTest
{
public class Helper
{
public delegate bool Condition(Book book);
public bool ConditionTitle(Book book)
{
return book.Title == "Book2";
}
public bool ConditionPrice(Book book)
{
return book.Price >= 50;
}
public static IList<Book> SearchBookByCondition(Condition condition)
{
IList<Book> books = new List<Book> {
new Book { Title = "Book1", Author = "Author1", ISBN = "ISBN1", Price = 30 },
new Book { Title = "Book2", Author = "Author2", ISBN = "ISBN2", Price = 40 },
new Book { Title = "Book3", Author = "Author3", ISBN = "ISBN3", Price = 50 },
new Book { Title = "Book4", Author = "Author4", ISBN = "ISBN4", Price = 60 }
};
IList<Book> results = new List<Book>();
foreach (Book book in books)
{
if (condition(book))
{
results.Add(book);
}
}
return results;
}
}
}
Program.csクラス:
using System;
using System.Collections.Generic;
using System.Text;
namespace LINQTest
{
class Program
{
static void Main(string[] args)
{
//Helper.Condition condition = new Helper.Condition(new Helper().ConditionTitle);
Helper.Condition condition = new Helper().ConditionTitle;
foreach (Book book in Helper.SearchBookByCondition(condition))
{
Console.WriteLine("{0}-{1}", book.Title, book.Price);
}
}
}
}
以上の実装方式は依頼delegateを採用し,C#2.0では匿名の方法も提供され,集合中のクエリ条件をフィルタするコードは以下のように変更できる.
Helper.Condition condition = delegate(Book book) { return book.Title == "Book2"; };
IList<Book> results = Helper.SearchBookByCondition(delegate(Book book) { return book.Title == "Book2"; });
C#3.0でLambda式が提供されると、集合フィルタリングは以下のように実現される.
IList<Book> results = Helper.SearchBookByCondition(book => book.Title == "Book2");
しかし、このように実現するには毎回クラス名Helperが必要であり、IList自身がこの方法を持っていることを望んでおり、C#3.0は拡張方法を提供している.
3、C#3.0拡張方法の実現方式
public static class Helper
{
public delegate bool Condtion(Book book);
public static IList<Book> Where(this IList<Book> books, Condtion condition)
{
IList < Book > results = new List<Book>();
foreach (Book book in books)
{
if (condition(book))
{
results.Add(book);
}
}
return results;
}
}
IList<Book> results = books.Where(book => book.Title == "Book2");
5、IEnumberable実現方式
IListはIEnumberableから継承されているため、IEnumberableを拡張することによって実現することができる.
public static class Helper
{
public delegate bool Condtion<T>(T t);
public static IEnumerable<T> Where<T>(this IEnumerable<T> items, Condtion<T> condition)
{
foreach (T t in items)
{
if (condition(t))
{
yield return t;
}
}
}
}
6、汎用拡張クラス
using System;
using System.Collections.Generic;
using System.Text;
namespace LINQTest
{
public class Extension
{
public delegate TResult Func<T, TResult>(T t);
public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> filter)
{
foreach (T item in source)
{
if (filter(item))
{
yield return item;
}
}
}
public static IEnumerable<TResult> Select<T, TResult>(this IEnumerable<T> source, Func<T, TResult> selector)
{
foreach (T item in source)
{
yield return selector(item);
}
}
}
}
var result = books.Where(book => book.Title == "Book2").Select(book => new {
Key = book.Title,Value=book.Price
});