Linq的學習 這裡繼續使用之前文章創建的學生類,首先簡單介紹一下linq的使用。 Student.cs public class Student { public int Id { get; set; } public int ClassId { get; set; } public string ...
Linq的學習
這裡繼續使用之前文章創建的學生類,首先簡單介紹一下linq的使用。
Student.cs
public class Student
{
public int Id { get; set; }
public int ClassId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Description { get; set; }
public void Study()
{
Console.WriteLine($"{this.Id} {this.Name} 跟著老師學習 .Net開發");
}
public void StudyQt()
{
Console.WriteLine($"{this.Id} {this.Name} 跟著老師學習C++ Qt");
}
}
初始化學生數據
public class LinqPrinciple
{
private List<Student> GetStudentsList()
{
List<Student> students = new List<Student>()
{ new Student() { Id = 1, ClassId = 1, Name = "張三", Age = 20, Description = "張三是一個好學生" },
new Student() { Id = 2, ClassId = 1, Name = "李四", Age = 21, Description = "李四是一個好學生" },
new Student() { Id = 3, ClassId = 2, Name = "王五", Age = 22, Description = "王五是一個好學生" },
new Student() { Id = 4, ClassId = 2, Name = "趙六", Age = 23, Description = "趙六是一個好學生" },
new Student() { Id = 5, ClassId = 3, Name = "孫七", Age = 24, Description = "孫七是一個好學生" },
new Student() { Id = 6, ClassId = 3, Name = "周八", Age = 25, Description = "周八是一個好學生" },
new Student() { Id = 7, ClassId = 1, Name = "綠春", Age = 30, Description = "張三是一個好學生" },
new Student() { Id = 8, ClassId = 1, Name = "麻醉", Age = 35, Description = "李四是一個好學生" },
new Student() { Id = 9, ClassId = 2, Name = "開天", Age = 26, Description = "王五是一個好學生" },
new Student() { Id = 10, ClassId = 2, Name = "匹敵", Age = 22, Description = "趙六是一個好學生" },
new Student() { Id = 11, ClassId = 3, Name = "獨輪車", Age = 23, Description = "孫七是一個好學生" },
new Student() { Id = 12, ClassId = 3, Name = "火箭英", Age = 20, Description = "周八是一個好學生" }
};
return students;
}
}
下麵寫幾個簡單的linq的語句,大概知道一下它的使用.
public void Show()
{
//獲取一下ClassID為3的學生們
List<Student> students = GetStudentsList();
List<Student> studentsId=students.Where(s => s.ClassId == 3).ToList();
Console.WriteLine("********************************1*****************************");
foreach (var student in studentsId)
{
Console.WriteLine($"{student.Id} {student.Name} {student.Age} {student.Description}");
}
Console.WriteLine("********************************2*****************************");
//獲取一下年紀大於24的學生們
List<Student> studentsAge = students.Where(s => s.Age > 24).ToList();
foreach (var student in studentsAge)
{
Console.WriteLine($"{student.Id} {student.Name} {student.Age} {student.Description}");
}
Console.WriteLine("********************************3*****************************");
//獲取一下年紀小於23同時ClassID為2的學生們
List<Student> studentsAgeClassId = students.Where(s => s.Age < 23 && s.ClassId == 2).ToList();
foreach (var student in studentsAgeClassId)
{
Console.WriteLine($"{student.Id} {student.Name} {student.Age} {student.Description}");
}
}
linq的原理的探究
下麵嘗試探索一下這個linq的本質是什麼?
嘗試自己實現一下這3個需求代碼,如下
List<Student> students = GetStudentsList();
List<Student> studentsId=new List<Student>();
foreach (var student in students)
{
if (student.ClassId == 3)
{
studentsId.Add(student);
}
}
List<Student> studentsAge=new List<Student>();
foreach (var student in students)
{
if (student.Age > 24)
{
studentsAge.Add(student);
}
}
List<Student> studentsAgeClassId=new List<Student>();
foreach (var student in students)
{
if (student.Age < 23 && student.ClassId == 2)
{
studentsAgeClassId.Add(student);
}
}
這上面的代碼有什麼問題?
大量的重覆代碼---最好是封裝一些,把重覆的代碼統一封裝;
這裡使用一個解決方案
封裝一個方法,將判斷的邏輯獨立到一個小方法中去.
public static bool IsOk01(Student student)
{
return student.ClassId == 3;
}
public static bool IsOk02(Student student)
{
return student.Age > 24;
}
public static bool IsOk03(Student student)
{
return student.Age < 23 && student.ClassId == 2;
}
public static List<Student> DragonWhere(List<Student> studentlist,Func<Student,bool> Func)
{
List<Student> students = new List<Student>();
foreach (var student in studentlist)
{
if (Func(student))
{
students.Add(student);
}
}
return students;
}
嘗試使用一下封裝的函數
List<Student> students = GetStudentsList();
List<Student> studentId= MethodExtension.DragonWhere(students, MethodExtension.IsOk01);
這裡還可以使用擴展方法和lambda表達式進一步的優化我們的代碼
public static List<Student> DragonWhere(this List<Student> studentlist,Func<Student,bool> Func)
{
List<Student> students = new List<Student>();
foreach (var student in studentlist)
{
if (Func(student))
{
students.Add(student);
}
}
return students;
}
在調用的時候,
List<Student> students = GetStudentsList();
List<Student> studentsId = students.DragonWhere(s => s.ClassId == 3);
這裡就串聯上了我們之前學到的知識,最後為了支持多種數據類型,使用上泛型,最後我們就得到了最終封裝的方法.
public static List<T> DragonWhere<T>(this List<T> studentlist,Func<T,bool> Func)
{
List<T> students = new List<T>();
foreach (var student in studentlist)
{
if (Func(student))
{
students.Add(student);
}
}
return students;
}
這裡也要使用ilspy反編譯一下它們的實現是如何?
看起來跟我們自己實現的Where差不多的樣子.
再去看一下它的movenext函數.
這個就是一個yield return反彙編出來的狀態機的代碼。
linq常見的語句
public void Show()
{
List<Student> studentList = this.GetStudentList();
#region Linq 擴展方法&表達式
{
var list = studentList.Where<Student>(s => s.Age < 30); //list裡面必然是符合要求的數據;
foreach (var item in list)
{
Console.WriteLine("Name={0} Age={1}", item.Name, item.Age);
}
}
{
Console.WriteLine("********************");
var list = from s in studentList
where s.Age < 30
select s; //list裡面必然是符合要求的數據;
foreach (var item in list)
{
Console.WriteLine("Name={0} Age={1}", item.Name, item.Age);
}
}
#endregion
#region linq to object Show
{
Console.WriteLine("********************");
var list = studentList.Where<Student>(s => s.Age < 30)
.Select(s => new //投影:可以做一些自由組裝+ new 一個匿名類,也可以new 具體類;
{
IdName = s.Id + s.Name,
ClassName = s.ClassId == 2 ? "高級班" : "其他班"
});
foreach (var item in list)
{
Console.WriteLine("Name={0} Age={1}", item.ClassName, item.IdName);
}
}
{
Console.WriteLine("********************");
var list = from s in studentList
where s.Age < 30
select new
{
IdName = s.Id + s.Name,
ClassName = s.ClassId == 2 ? "高級班" : "其他班"
};
foreach (var item in list)
{
Console.WriteLine("Name={0} Age={1}", item.ClassName, item.IdName);
}
}
{
Console.WriteLine("********************");
var list = studentList.Where<Student>(s => s.Age < 30)//條件過濾
.Select(s => new//投影
{
Id = s.Id,
ClassId = s.ClassId,
IdName = s.Id + s.Name,
ClassName = s.ClassId == 2 ? "高級班" : "其他班"
})
.OrderBy(s => s.Id)//排序 升序
.ThenBy(s => s.ClassName) //多重排序,可以多個欄位排序都生效
.OrderByDescending(s => s.ClassId)//倒排
.Skip(2)//跳過幾條 //必須要先排序
.Take(3)//獲取幾條 //必須要先排序
;
foreach (var item in list)
{
Console.WriteLine($"Name={item.ClassName} Age={item.IdName}");
}
}
{//group by·
Console.WriteLine("********************");
var list = from s in studentList
where s.Age < 30
group s by s.ClassId into sg
select new
{
key = sg.Key,
maxAge = sg.Max(t => t.Age)
};
foreach (var item in list)
{
Console.WriteLine($"key={item.key} maxAge={item.maxAge}");
}
//group by new {s.ClassId,s.Age}
//group by new {A=s.ClassId>1}
}
{
Console.WriteLine("********************");
var list = studentList.GroupBy(s => s.ClassId).Select(sg => new
{
key = sg.Key,
maxAge = sg.Max(t => t.Age)
});
foreach (var item in list)
{
Console.WriteLine($"key={item.key} maxAge={item.maxAge}");
}
}
{
var list = studentList.GroupBy(s => s.ClassId);
foreach (var date in list) ///實現了IEnumerable
{
Console.WriteLine(date.Key);
foreach (var item in date)
{
Console.WriteLine(item.Age);
}
}
}
List<Class> classList = new List<Class>()
{
new Class()
{
Id=1,
ClassName="架構班"
},
new Class()
{
Id=2,
ClassName="高級班"
},
new Class()
{
Id=3,
ClassName="全棧班"
},
};
{
//Join
var list = from s in studentList
join c in classList on s.ClassId equals c.Id //只能使用equals 不能使==
select new
{
Name = s.Name,
CalssName = c.ClassName
};
foreach (var item in list)
{
Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
}
}
{
var list = studentList.Join(classList, s => s.ClassId, c => c.Id, (s, c) => new
{
Name = s.Name,
CalssName = c.ClassName
});
foreach (var item in list)
{
Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
}
}
{//左連接
var list = from s in studentList
join c in classList on s.ClassId equals c.Id
into scList
from sc in scList.DefaultIfEmpty()//
select new
{
Name = s.Name,
CalssName = sc == null ? "無班級" : sc.ClassName//c變sc,為空則用
};
foreach (var item in list)
{
Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
}
Console.WriteLine(list.Count());
}
{
var list = studentList.Join(classList, s => s.ClassId, c => c.Id, (s, c) => new
{
Name = s.Name,
CalssName = c.ClassName
}).DefaultIfEmpty();//為空就沒有了
foreach (var item in list)
{
Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
}
Console.WriteLine(list.Count());
}
{
//左連接和右鏈接 就是鏈接對象交換一下即可;
}
#endregion
}