https://atnd.org/events/57085
• 
• 
• http://blog.shos.info 
• 
•
• 
http://slidesha.re/1tA0Tit 
• 
http://1drv.ms/1zs3n78 
3 
ソースコード 
参照
•
1. 
2. 
3. 
4. 
5.
• 
IEnumerable<int> sequence1 = new[] { 1, 1, 2, 3, 5, 8, 13, 21, 34 }; 
IEnumerable<int> sequence2 = sequence1.Where (x => x % 2 == 0); 
IEnumerable<int> sequence3 = sequence2.Select (x => x * x ); 
foreach (int item in sequence3) 
Console.WriteLine(item); 
ソースコード 
参照
•
• 
ソースコード 
参照 
IEnumerable<int> sequence1 = new[] { 1, 1, 2, 3, 5, 8, 13, 21, 34 }; 
IEnumerable<int> sequence2 = sequence1.Where (x => x % 2 == 0); 
IEnumerable<int> sequence3 = sequence2.Select (x => x * x ); 
foreach (int item in sequence3) 
Console.WriteLine(item); 実際にsequence3 から値が取り出さ 
れるまで、sequence1 から値は取り 
出されず、Where やSelect に渡した 
デリゲートも実行されない
• 
var data = new EmployeeDataClassesDataContext(); 
data.Log = Console.Out; 
var sequence1 = data.Employee; 
var sequence2 = sequence1.Where ( 
ソースコード 
参照 
employee => employee.Name.Contains("田") ); 
var sequence3 = sequence2.Select ( 
employee => new { 番号= employee.Id, 名前= employee.Name }); 
foreach (var employee in sequence3) 
Console.WriteLine("{0}: {1}", employee.番号, employee.名前);
• 
SELECT [t0].[Id], [t0].[Name] 
FROM [dbo].[Employee] AS [t0] 
• 
SELECT [t0].[Id] AS [番号], [t0].[Name] AS [名前] 
FROM [dbo].[Employee] AS [t0] 
WHERE [t0].[Name] LIKE @p0 
-- @p0: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [%田%]
• 
public static class Enumerable 
{ 
public static class Queryable 
{ 
public static IQueryable<T> Where<T>(this IQueryable<T> source, 
Expression<Func<T, bool>> predicate); 
} 
public static IEnumerable<T> Where<T>(this IEnumerable<T> source, 
Func<T, int, bool> predicate); 
} 
•
• 
• 
•
• 
class Program 
{ 
static void Main() 
{ 
ソースコード 
Func<int, int, int> sequence1 = (x, y) => x + y; 
Func<int, int, int> sequence2 = (x, y) => { return x + y; }; 
Expression<Func<int, int, int>> expression1 = (x, y) => x + y; 
//Expression<Func<int, int, int>> expression2 = (x, y) => 
{ return x + y; }; 
} 
} 
ブロックが含まれるラムダ式は式として扱えない 
(IQueryable<T> には使えない) 
参照
• 
• 
var sequence4 = from employee in data.Employee 
where employee.Name.Contains("田") 
select new { 番号= employee.Id, 
名前= employee.Name };
• 
•
• 
• http://msdn.microsoft.com/ja-jp/library/system.linq.iqueryable(v=vs.110).aspx 
public interface IQueryable : IEnumerable 
{ 
Type ElementType { get; } 
Expression Expression { get; } 
IQueryProvider Provider { get; } 
} 
public interface IQueryable<T> : IEnumerable<T>, IQueryable 
{}
• 
class Foo : IQueryable 
{ 
public Type ElementType 
{ get { throw new NotImplementedException(); } } 
public Expression Expression 
{ get { throw new NotImplementedException(); } } 
public IQueryProvider Provider 
{ get { throw new NotImplementedException(); } } 
public IEnumerator GetEnumerator() 
{ throw new NotImplementedException(); } 
} 
ソースコード 
参照
• 
ソースコード 
参照 
Expression<Func<int, int, int>> expression = (x, y) => x + y; 
((Expression)expression).Show();
•
•
•
•
•
• 
• 
• 
• 
• 
Assembly Module 
Type 
・Class 
・Interface 
・Value Type 
FieldInfo 
PropertyInfo 
EventInfo 
MethodInfo 
ConstructorInfo ParameterInfo
• 
• 
• 
•
• 
• 
•
• 
• 
• 
• 
• 
•
• 
• 
• 
•
• 
• 
• 
CodeDOM CodeDOMProvider 
ソースコード 
(C#、VB、JScript) 
アセンブリ 
GenerateCodeFromNamespace 
CompileAssemblyFromDom
• 
• 
• 
•
• 
namespace CodeDomHelloWorldDemo 
{ 
using System; 
class Program 
{ 
static void Main() 
{ 
Console.WriteLine("Hello world!"); 
Console.ReadKey(); 
} 
} 
} 
ソースコード 
参照
• 
• 
• 
• http://msdn.microsoft.com/ja-jp/library/f7dy01k1(v=vs.110).aspx
• 
•
Expression<Func<Employee, bool>> expression = employee => employee.Name.Contains("山"); 
Parameters 
Body Object 
Method 
Arguments 
Expression 
Member 
employee => 
employee.Name.Con 
tains("山") 
employee.Name 
Contains 
employee 
Name 
“山” 
employee 
employee.Name.Co 
ntains("山")
• 
1. 
2. 
+ 
=> 
x y 
(x, y)
• Expression の派生クラス一覧- 継承階層- Expression クラス- MSDN ライブラリ
パラメーターのx とy は、(x, y) 部分 
とx + y 部分で使われているが、 
それぞれ1 インスタンスずつにする
• 
static Func<int, int, int> AddByExpression() 
{ 
// 生成したい式 
// (int x, int y) => x + y 
// 引数x の式 
var x = Expression.Parameter(type: typeof(int)); 
// 引数y の式 
var y = Expression.Parameter(type: typeof(int)); 
// x + y の式 
var add = Expression.Add (left: x, right: y); 
// (x, y) => x + y の式 
var lambda = Expression.Lambda (add, x, y ); 
// ラムダ式をコンパイルしてデリゲートとして返す 
return (Func<int, int, int>)lambda.Compile(); 
} 
ソースコード 
参照
• 
static Func<int, int, int> AddByExpression() 
{ 
// 生成したい式 
// (int x, int y) => x + y 
// 引数x の式 
var x = Expression.Parameter(type: typeof(int)); 
// 引数y の式 
var y = Expression.Parameter(type: typeof(int)); 
// x + y の式 
var add = Expression.Add (left: x, right: y); 
// (x, y) => x + y の式 
var lambda = Expression.Lambda (add, x, y ); 
// ラムダ式をコンパイルしてデリゲートとして返す 
return (Func<int, int, int>)lambda.Compile(); 
} 
ソースコード 
参照
• 
1. 
2. 
3. 
• 
1. 
2. 
3. 
4.
•
•
• 
// Expression (式) によるメソッド呼び出しメソッドの生成 
static Func<T, TResult> CallByExpression<T, TResult>(string methodName) 
{ 
// 生成したい式の例: 
// (T item) => item.methodName() 
// 引数item の式 
var parameterExpression = Expression.Parameter(type: typeof(T), name: 
"item"); 
// item.methodName() の式 
var callExpression = Expression.Call( 
instance: parameterExpression, 
method : typeof(T).GetMethod(methodName, Type.EmptyTypes) 
); 
// item => item.methodName() の式 
var lambda = Expression.Lambda(callExpression, parameterExpression); 
// ラムダ式をコンパイルしてデリゲートとして返す 
return (Func<T, TResult>)lambda.Compile(); 
} 
ソースコード 
参照
• 
•
• 
1. 
2.
• 
1. 
2. 
1. 
2. 
3. 
1. 
2. 
3. 
4. 
1. 
2. 
3.
•
•
• 
• 
• 
• 
• http://blog.jhashimoto.net/entry/20120616/1339806360
• 
• http://msdn.microsoft.com/ja-jp/library/bb546158.aspx 
• 
• http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx 
• 
• http://weblogs.asp.net/mehfuzh/writing-custom-linq-provider
LINQプロバイダー 
(IQueryProvider) 
クエリーコンテキスト 
式 
クエリー 
(IQueryable) 
式を解釈
• 
• 
• 
•
• ソースコード 
pubic class QueryProvider : IQueryProvider 
{ 
public IQueryable<TCollection> 
CreateQuery<TCollection>(Expression expression) 
{ return new QueryableData<TCollection>(this, expression); } 
IQueryable IQueryProvider.CreateQuery(Expression expression) 
{ return null; } 
public TResult Execute<TResult>(Expression expression) 
{ return default(TResult); } 
public object Execute(Expression expression) 
{ 
// ここで式木を解釈して、IEnumerable を作って返す 
} 
} 
参照
• 
• 
•
• 
static void Main() 
{ 
IQueryable<int> query1 = new QueryableData<int>(new QueryProvider()); 
Console.WriteLine(query1.Expression); 
IQueryable<int> query2 = query1.Where(x => x % 2 == 0); 
Console.WriteLine(query2.Expression); 
IQueryable<int> query3 = query2.OrderBy(x => x); 
Console.WriteLine(query3.Expression); 
IQueryable<int> query4 = query3.Select(x => x * x); 
Console.WriteLine(query4.Expression); 
foreach (int item in query4) 
Console.WriteLine(item); 
} 
ソースコード 
参照
• 
value(ProviderSample.QueryableData`1[System.Int32]) 
value(ProviderSample.QueryableData`1[System.Int32]).Where(x => ((x % 2) == 0)) 
value(ProviderSample.QueryableData`1[System.Int32]).Where(x => ((x % 2) == 0)).OrderBy(x 
=> x) 
value(ProviderSample.QueryableData`1[System.Int32]).Where(x => ((x % 2) == 0)).OrderBy(x 
=> x).Select(x => (x * x)) 
1 
1 
2 
3 
5 
8 
13 
21 
34
• 
•
• 
public class MyExpressionVisitor : ExpressionVisitor 
{ 
protected override Expression VisitBinary(BinaryExpression expression) 
{ return base.VisitBinary(expression); } 
protected override Expression VisitConstant(ConstantExpression expression) 
{ return base.VisitConstant(expression); } 
protected override Expression VisitMethodCall(MethodCallExpression expression) 
{ return base.VisitMethodCall(expression); } 
protected override Expression VisitParameter(ParameterExpression expression) 
{ return base.VisitParameter(expression); } 
…… 等々…… 
} 
ソースコード 
参照
• 
☆式(x, y) => x + y 
二項演算((x + y)) - 右辺: x, 左辺: y, 型: System.Int32 
引数(x) - 名前: x, 型: System.Int32 
引数(y) - 名前: y, 型: System.Int32 
引数(x) - 名前: x, 型: System.Int32 
引数(y) - 名前: y, 型: System.Int32 
☆式text => text.Contains("福") 
メソッドコール(text.Contains("福")) - メソッド名: Contains, 型: System.Boolean 
引数(text) - 名前: text, 型: System.String 
定数("福") - 値: 福, 型: System.String 
引数(text) - 名前: text, 型: System.String
• 
public class QueryableTimeline<TElement> : IOrderedQueryable<TElement> 
{ 
public IQueryProvider Provider { get; private set; } 
public Expression Expression { get; private set; } 
public Type ElementType 
{ get { return typeof(TElement); } } 
public QueryableTimeline() 
{ 
Provider = new TimelineQueryProvider(); 
Expression = Expression.Constant(this); 
} 
…… 途中省略…… 
} 
ソースコード 
参照
•

C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~

  • 1.
  • 2.
    • • •http://blog.shos.info • •
  • 3.
    • http://slidesha.re/1tA0Tit • http://1drv.ms/1zs3n78 3 ソースコード 参照
  • 4.
  • 5.
    1. 2. 3. 4. 5.
  • 7.
    • IEnumerable<int> sequence1= new[] { 1, 1, 2, 3, 5, 8, 13, 21, 34 }; IEnumerable<int> sequence2 = sequence1.Where (x => x % 2 == 0); IEnumerable<int> sequence3 = sequence2.Select (x => x * x ); foreach (int item in sequence3) Console.WriteLine(item); ソースコード 参照
  • 8.
  • 9.
    • ソースコード 参照 IEnumerable<int> sequence1 = new[] { 1, 1, 2, 3, 5, 8, 13, 21, 34 }; IEnumerable<int> sequence2 = sequence1.Where (x => x % 2 == 0); IEnumerable<int> sequence3 = sequence2.Select (x => x * x ); foreach (int item in sequence3) Console.WriteLine(item); 実際にsequence3 から値が取り出さ れるまで、sequence1 から値は取り 出されず、Where やSelect に渡した デリゲートも実行されない
  • 11.
    • var data= new EmployeeDataClassesDataContext(); data.Log = Console.Out; var sequence1 = data.Employee; var sequence2 = sequence1.Where ( ソースコード 参照 employee => employee.Name.Contains("田") ); var sequence3 = sequence2.Select ( employee => new { 番号= employee.Id, 名前= employee.Name }); foreach (var employee in sequence3) Console.WriteLine("{0}: {1}", employee.番号, employee.名前);
  • 12.
    • SELECT [t0].[Id],[t0].[Name] FROM [dbo].[Employee] AS [t0] • SELECT [t0].[Id] AS [番号], [t0].[Name] AS [名前] FROM [dbo].[Employee] AS [t0] WHERE [t0].[Name] LIKE @p0 -- @p0: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [%田%]
  • 13.
    • public staticclass Enumerable { public static class Queryable { public static IQueryable<T> Where<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate); } public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, int, bool> predicate); } •
  • 14.
  • 15.
    • class Program { static void Main() { ソースコード Func<int, int, int> sequence1 = (x, y) => x + y; Func<int, int, int> sequence2 = (x, y) => { return x + y; }; Expression<Func<int, int, int>> expression1 = (x, y) => x + y; //Expression<Func<int, int, int>> expression2 = (x, y) => { return x + y; }; } } ブロックが含まれるラムダ式は式として扱えない (IQueryable<T> には使えない) 参照
  • 16.
    • • varsequence4 = from employee in data.Employee where employee.Name.Contains("田") select new { 番号= employee.Id, 名前= employee.Name };
  • 17.
  • 18.
    • • http://msdn.microsoft.com/ja-jp/library/system.linq.iqueryable(v=vs.110).aspx public interface IQueryable : IEnumerable { Type ElementType { get; } Expression Expression { get; } IQueryProvider Provider { get; } } public interface IQueryable<T> : IEnumerable<T>, IQueryable {}
  • 19.
    • class Foo: IQueryable { public Type ElementType { get { throw new NotImplementedException(); } } public Expression Expression { get { throw new NotImplementedException(); } } public IQueryProvider Provider { get { throw new NotImplementedException(); } } public IEnumerator GetEnumerator() { throw new NotImplementedException(); } } ソースコード 参照
  • 21.
    • ソースコード 参照 Expression<Func<int, int, int>> expression = (x, y) => x + y; ((Expression)expression).Show();
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 28.
    • • • • • Assembly Module Type ・Class ・Interface ・Value Type FieldInfo PropertyInfo EventInfo MethodInfo ConstructorInfo ParameterInfo
  • 30.
  • 31.
  • 32.
    • • • • • •
  • 33.
  • 35.
    • • • CodeDOM CodeDOMProvider ソースコード (C#、VB、JScript) アセンブリ GenerateCodeFromNamespace CompileAssemblyFromDom
  • 36.
  • 37.
    • namespace CodeDomHelloWorldDemo { using System; class Program { static void Main() { Console.WriteLine("Hello world!"); Console.ReadKey(); } } } ソースコード 参照
  • 38.
    • • • • http://msdn.microsoft.com/ja-jp/library/f7dy01k1(v=vs.110).aspx
  • 39.
  • 40.
    Expression<Func<Employee, bool>> expression= employee => employee.Name.Contains("山"); Parameters Body Object Method Arguments Expression Member employee => employee.Name.Con tains("山") employee.Name Contains employee Name “山” employee employee.Name.Co ntains("山")
  • 42.
    • 1. 2. + => x y (x, y)
  • 43.
    • Expression の派生クラス一覧-継承階層- Expression クラス- MSDN ライブラリ
  • 44.
    パラメーターのx とy は、(x,y) 部分 とx + y 部分で使われているが、 それぞれ1 インスタンスずつにする
  • 45.
    • static Func<int,int, int> AddByExpression() { // 生成したい式 // (int x, int y) => x + y // 引数x の式 var x = Expression.Parameter(type: typeof(int)); // 引数y の式 var y = Expression.Parameter(type: typeof(int)); // x + y の式 var add = Expression.Add (left: x, right: y); // (x, y) => x + y の式 var lambda = Expression.Lambda (add, x, y ); // ラムダ式をコンパイルしてデリゲートとして返す return (Func<int, int, int>)lambda.Compile(); } ソースコード 参照
  • 46.
    • static Func<int,int, int> AddByExpression() { // 生成したい式 // (int x, int y) => x + y // 引数x の式 var x = Expression.Parameter(type: typeof(int)); // 引数y の式 var y = Expression.Parameter(type: typeof(int)); // x + y の式 var add = Expression.Add (left: x, right: y); // (x, y) => x + y の式 var lambda = Expression.Lambda (add, x, y ); // ラムダ式をコンパイルしてデリゲートとして返す return (Func<int, int, int>)lambda.Compile(); } ソースコード 参照
  • 47.
    • 1. 2. 3. • 1. 2. 3. 4.
  • 48.
  • 49.
  • 50.
    • // Expression(式) によるメソッド呼び出しメソッドの生成 static Func<T, TResult> CallByExpression<T, TResult>(string methodName) { // 生成したい式の例: // (T item) => item.methodName() // 引数item の式 var parameterExpression = Expression.Parameter(type: typeof(T), name: "item"); // item.methodName() の式 var callExpression = Expression.Call( instance: parameterExpression, method : typeof(T).GetMethod(methodName, Type.EmptyTypes) ); // item => item.methodName() の式 var lambda = Expression.Lambda(callExpression, parameterExpression); // ラムダ式をコンパイルしてデリゲートとして返す return (Func<T, TResult>)lambda.Compile(); } ソースコード 参照
  • 51.
  • 52.
  • 53.
    • 1. 2. 1. 2. 3. 1. 2. 3. 4. 1. 2. 3.
  • 54.
  • 55.
  • 58.
    • • • • • http://blog.jhashimoto.net/entry/20120616/1339806360
  • 59.
    • • http://msdn.microsoft.com/ja-jp/library/bb546158.aspx • • http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx • • http://weblogs.asp.net/mehfuzh/writing-custom-linq-provider
  • 60.
  • 61.
  • 62.
    • ソースコード pubicclass QueryProvider : IQueryProvider { public IQueryable<TCollection> CreateQuery<TCollection>(Expression expression) { return new QueryableData<TCollection>(this, expression); } IQueryable IQueryProvider.CreateQuery(Expression expression) { return null; } public TResult Execute<TResult>(Expression expression) { return default(TResult); } public object Execute(Expression expression) { // ここで式木を解釈して、IEnumerable を作って返す } } 参照
  • 63.
  • 64.
    • static voidMain() { IQueryable<int> query1 = new QueryableData<int>(new QueryProvider()); Console.WriteLine(query1.Expression); IQueryable<int> query2 = query1.Where(x => x % 2 == 0); Console.WriteLine(query2.Expression); IQueryable<int> query3 = query2.OrderBy(x => x); Console.WriteLine(query3.Expression); IQueryable<int> query4 = query3.Select(x => x * x); Console.WriteLine(query4.Expression); foreach (int item in query4) Console.WriteLine(item); } ソースコード 参照
  • 65.
    • value(ProviderSample.QueryableData`1[System.Int32]) value(ProviderSample.QueryableData`1[System.Int32]).Where(x=> ((x % 2) == 0)) value(ProviderSample.QueryableData`1[System.Int32]).Where(x => ((x % 2) == 0)).OrderBy(x => x) value(ProviderSample.QueryableData`1[System.Int32]).Where(x => ((x % 2) == 0)).OrderBy(x => x).Select(x => (x * x)) 1 1 2 3 5 8 13 21 34
  • 66.
  • 67.
    • public classMyExpressionVisitor : ExpressionVisitor { protected override Expression VisitBinary(BinaryExpression expression) { return base.VisitBinary(expression); } protected override Expression VisitConstant(ConstantExpression expression) { return base.VisitConstant(expression); } protected override Expression VisitMethodCall(MethodCallExpression expression) { return base.VisitMethodCall(expression); } protected override Expression VisitParameter(ParameterExpression expression) { return base.VisitParameter(expression); } …… 等々…… } ソースコード 参照
  • 68.
    • ☆式(x, y)=> x + y 二項演算((x + y)) - 右辺: x, 左辺: y, 型: System.Int32 引数(x) - 名前: x, 型: System.Int32 引数(y) - 名前: y, 型: System.Int32 引数(x) - 名前: x, 型: System.Int32 引数(y) - 名前: y, 型: System.Int32 ☆式text => text.Contains("福") メソッドコール(text.Contains("福")) - メソッド名: Contains, 型: System.Boolean 引数(text) - 名前: text, 型: System.String 定数("福") - 値: 福, 型: System.String 引数(text) - 名前: text, 型: System.String
  • 69.
    • public classQueryableTimeline<TElement> : IOrderedQueryable<TElement> { public IQueryProvider Provider { get; private set; } public Expression Expression { get; private set; } public Type ElementType { get { return typeof(TElement); } } public QueryableTimeline() { Provider = new TimelineQueryProvider(); Expression = Expression.Constant(this); } …… 途中省略…… } ソースコード 参照
  • 70.