述語フィルターの動的指定。
成果物
情報源
- https://docs.microsoft.com/ja-jp/dotnet/csharp/linq/dynamically-specify-predicate-filters-at-runtime
コード
Contains
Student.cs
public class Student { #region data public enum GradeLevel { FirstYear = 1, SecondYear, ThirdYear, FourthYear }; public string FirstName { get; set; } public string LastName { get; set; } public int Id { get; set; } public GradeLevel Year; public List<int> ExamScores; protected static List<Student> students = new List<Student> { new Student {FirstName = "Terry", LastName = "Adams", Id = 120, Year = GradeLevel.SecondYear, ExamScores = new List<int> { 99, 82, 81, 79}}, new Student {FirstName = "Fadi", LastName = "Fakhouri", Id = 116, Year = GradeLevel.ThirdYear, ExamScores = new List<int> { 99, 86, 90, 94}}, new Student {FirstName = "Hanying", LastName = "Feng", Id = 117, Year = GradeLevel.FirstYear, ExamScores = new List<int> { 93, 92, 80, 87}}, new Student {FirstName = "Cesar", LastName = "Garcia", Id = 114, Year = GradeLevel.FourthYear, ExamScores = new List<int> { 97, 89, 85, 82}}, new Student {FirstName = "Debra", LastName = "Garcia", Id = 115, Year = GradeLevel.ThirdYear, ExamScores = new List<int> { 35, 72, 91, 70}}, new Student {FirstName = "Hugo", LastName = "Garcia", Id = 118, Year = GradeLevel.SecondYear, ExamScores = new List<int> { 92, 90, 83, 78}}, new Student {FirstName = "Sven", LastName = "Mortensen", Id = 113, Year = GradeLevel.FirstYear, ExamScores = new List<int> { 88, 94, 65, 91}}, new Student {FirstName = "Claire", LastName = "O'Donnell", Id = 112, Year = GradeLevel.FourthYear, ExamScores = new List<int> { 75, 84, 91, 39}}, new Student {FirstName = "Svetlana", LastName = "Omelchenko", Id = 111, Year = GradeLevel.SecondYear, ExamScores = new List<int> { 97, 92, 81, 60}}, new Student {FirstName = "Lance", LastName = "Tucker", Id = 119, Year = GradeLevel.ThirdYear, ExamScores = new List<int> { 68, 79, 88, 92}}, new Student {FirstName = "Michael", LastName = "Tucker", Id = 122, Year = GradeLevel.FirstYear, ExamScores = new List<int> { 94, 92, 91, 91}}, new Student {FirstName = "Eugene", LastName = "Zabokritski", Id = 121, Year = GradeLevel.FourthYear, ExamScores = new List<int> { 96, 85, 91, 60}} }; #endregion // Helper method, used in GroupByRange. protected static int GetPercentile(Student s) { double avg = s.ExamScores.Average(); return avg > 0 ? (int)avg / 10 : 0; } public static void QueryHighScores(int exam, int score) { var highScores = from student in students where student.ExamScores[exam] > score select new {Name = student.FirstName, Score = student.ExamScores[exam]}; foreach (var item in highScores) { Console.WriteLine($"{item.Name,-15}{item.Score}"); } } }
QueryById
の引数を起動引数にすれば実行時に変更できる。
Main.cs
class DynamicPredicates : Student { public void Main(string[] args=null) { string[] ids = { "111", "114", "112" }; QueryById(ids); Console.WriteLine("Press any key to exit."); Console.ReadKey(); } private void QueryById(string[] ids) { var queryNames = from student in students let i = student.Id.ToString() where ids.Contains(i) select new { student.LastName, student.Id }; foreach (var name in queryNames) { Console.WriteLine($"{name.LastName}: {name.Id}"); } } } class Main { public void Run() { new DynamicPredicates().Main(); } }
Garcia: 114 O'Donnell: 112 Omelchenko: 111 Press any key to exit.
Switch
QueryByYear
の引数を起動引数にすれば実行時に変更できる。
Main.cs
class DynamicPredicates : Student { public void Main(string[] args=null) { string[] ids = { "111", "114", "112" }; QueryByYear("1"); Console.WriteLine("Press any key to exit."); Console.ReadKey(); } private void QueryByYear(string level) { GradeLevel year = (GradeLevel)Convert.ToInt32(level); IEnumerable<Student> studentQuery = null; switch (year) { case GradeLevel.FirstYear: studentQuery = from student in students where student.Year == GradeLevel.FirstYear select student; break; case GradeLevel.SecondYear: studentQuery = from student in students where student.Year == GradeLevel.SecondYear select student; break; case GradeLevel.ThirdYear: studentQuery = from student in students where student.Year == GradeLevel.ThirdYear select student; break; case GradeLevel.FourthYear: studentQuery = from student in students where student.Year == GradeLevel.FourthYear select student; break; default: break; } Console.WriteLine($"The following students are at level {year}"); foreach (Student name in studentQuery) { Console.WriteLine($"{name.LastName}: {name.Id}"); } } } class Main { public void Run() { new DynamicPredicates().Main(); } }
The following students are at level FirstYear Feng: 117 Mortensen: 113 Tucker: 122 Press any key to exit.
所感
クエリ式の条件where
にC#メソッドを指定すれば動的に指定できる。SQL構文とC#構文の合わせ技みたいなものか。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 5.0.3(1)-release
$ uname -a Linux raspberrypi 4.19.75-v7l+ #1270 SMP Tue Sep 24 18:51:41 BST 2019 armv7l GNU/Linux