やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

C#の概念 LINQ(述語フィルターの動的指定)

 述語フィルターの動的指定。

成果物

情報源

コード

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.

所感

 クエリ式の条件whereC#メソッドを指定すれば動的に指定できる。SQL構文とC#構文の合わせ技みたいなものか。

対象環境

$ uname -a
Linux raspberrypi 4.19.75-v7l+ #1270 SMP Tue Sep 24 18:51:41 BST 2019 armv7l GNU/Linux