50010702506256
分类:
.NET
?委托:
l 什么委托:
本质是方法指针
l 委托的作用:
作用:进行方法传递,方法可以当作一个参数进行传递,C#里边要传递方法需要借助委托
l 使用委托一般的步骤:
1:定义委托
public delegate 返回值 方法名称(参数);
2:委托可以关联方法
3:执行委托,就相当于执行方法
public static void Way() { Console.WriteLine("hello delegate"); } //1:定义一个无参数无返回值的委托 public delegate void DEL_Way(); static void Main(string[] args) { //2:给委托关联一个方法 DEL_Way delway = Way; //3:执行委托 delway.Invoke(); Console.ReadLine(); }
l 委托实现一个简单的定时器:
public class MyTimer
{
public void Start(Action way, int timespan)
{
while (true)
{
way();
System.Threading.Thread.Sleep(timespan);
}
}
} 执行:
MyTimer mytimer = new MyTimer(); mytimer.Start(Way, 1000);
?系统委托
作用:简化委托的定义,系统已经定义好,使用的时候直接使用,不需要重复定义
l 系统委托的主要分类
Action:无返回值,有0-16个参数
Func:有返回值,有0-16个参数
Predicate:固定返回值为bool
Comparison:固定返回值为int
其实后面两个完全可以使用func替换,但是为了一目了然一看就知道返回值是什么
l 实例
Action action = Way; action(); Action<int> action2 = Square; action2(6); Func<int, int, int> func = Add; int result = func(8, 8); Console.WriteLine(result);
?Lamdba表达式
l 作用:
lamdba表达式可以简化方法的定义
l 语法:
(方法参数)=>{方法体};
例如:无参无返回值的lamdba表达式
()=>{};
又如:一个参数无返回值
(a)=>{};
在如:一个参数一个返回值
(a)=>{return a*a};
还如:2个参数1个返回值
(a,b)=>{return a+b};
l 实例:
//无参无返回值的lamdba表达式
Action action = () => { Console.WriteLine("hello lamdba"); };
action();
//一个参数无返回值
Action<int> action2 = (a) => { Console.WriteLine(a * a); };
action2(6);
//一个参数一个返回值
Func<int, int> func = (a) => { return a * a; };
int square = func(8);
Console.WriteLine(square);
//2个参数1个返回值
Func<int, int, int> funcsum = (a, b) => { return a + b; };
int result = funcsum(3, 6);
Console.WriteLine(result);执行定时器的就可以用lamdba来简化方法:
MyTimer mytime = new MyTimer();
mytime.Start(() =>
{
Console.WriteLine("国庆快乐");
}, 1000);做一点简单的集合查询:
static void Main(string[] args)
{
List<string> fruitList = new List<string>() { "葡萄", "香蕉", "西瓜", "木瓜", "哈密瓜" };
Console.WriteLine("请输入查询名字");
string fruitName = Console.ReadLine();
var result = fruitList.Where(a => a.Contains(fruitName));
Console.ReadLine();
} 对象集合lamdba查询:
static void Main(string[] args)
{
List<Users> ulist = new List<Users>() {
new Users() {username="李清照", age=23, address="宋" },
new Users() {username="黄月英", age=18, address="三国" },
new Users() {username="黄忠", age=109, address="三国" },
new Users() {username="黄蓉", age=27, address="射雕" }
};
Console.WriteLine("请输入查询姓名");
string name = Console.ReadLine();
var result = ulist.Where(a => a.username.Contains(name)).OrderByDescending(a => a.age).ToList();
Console.ReadLine();
}?Lamdba表达式自己实现foreach,Where,FirstOrDefault,SelectMany
自己实现一下微软提供的集合查询也算是抛砖引玉了
public static class IEnumerableExtands
{
public static void MyForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (T item in source)
{
action(item);
}
}
//根据条件查询
public static IEnumerable<T> MyWhere<T>(this IEnumerable<T> source, Predicate<T> action)
{
List<T> list = new List<T>();
foreach (T item in source)
{
if (action(item))
{
list.Add(item);
}
}
return list;
}
//根据条件查询返回第一条或者默认值
public static T MyFirstOrDefault<T>(this IEnumerable<T> source, Predicate<T> action)
{
T val = default(T);
foreach (T item in source)
{
if (action(item))
{
return item;
}
}
return val;
}
}效果:

实现集合查询SelectMany
自己写一下里边的原理对了解它的用法有很大的帮助,select都作用类似就是把1对多的格式处理成1对1的格式,
比如这里的把UserScoreViewModel格式处理成UserScoreViewModel2

我们要想写通用的扩展方法出来可以先写一个专门的处理UserScoreViewModel格式成UserScoreViewModel2的方法,这样做也便于我们分析和理解问题,特别是如果我们要进行授课,这种方式更能够让学生理解,一步一步的深入。
其实很简单就是两个遍历就好
/// <summary>
/// 把List<UserScoreViewModel>转换成List<UserScoreViewModel2>格式
/// </summary>
public List<UserScoreViewModel2> Parse(List<UserScoreViewModel> source)
{
List<UserScoreViewModel2> result = new List<UserScoreViewModel2>();
foreach (UserScoreViewModel item in source)
{
foreach (Score scoreItem in item.scoreList)
{
UserScoreViewModel2 uscore = new UserScoreViewModel2();
uscore.UserName = item.UserName;
uscore.score = scoreItem;
result.Add(uscore);
}
}
return result;
}然后我们在去写通用的:
public static class IEnumberExtands
{
/// <summary>
/// 自己实现MySelectMany
/// </summary>
/// <typeparam name="TSource">对应外面的集合源类型</typeparam>
/// <typeparam name="TCollection">集合里边子集合类型</typeparam>
/// <typeparam name="TResult">返回值类型</typeparam>
/// <returns></returns>
public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
{
List<TResult> resultList = new List<TResult>();
foreach (TSource tsource in source)
{
//通过外面传递的lamdba拿到集合
IEnumerable<TCollection> sublist = collectionSelector(tsource);
foreach (TCollection item in sublist)
{
//通过外面传递的lamdba拿到返回对象
TResult result = resultSelector(tsource, item);
resultList.Add(result);
}
}
return resultList;
}
}上面的方法没有处理为空的情况,如果外面写了DefaultIfEmpty()就容易报错,所以我们可以使用反射创建一个默认对象处理一下这种情况,不然我们就只有在外面去处理了
public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
{
List<TResult> userScoreViewModel2List = new List<TResult>();
foreach (TSource item in source)
{
foreach (TCollection score in collectionSelector(item))
{
if (score == null)
{
//使用反射创建对象,避免为空报错,为空的时候我们就给一个默认值
TCollection collobj = Activator.CreateInstance<TCollection>();
TResult tresult = resultSelector(item, collobj);
userScoreViewModel2List.Add(tresult);
}
else
{
TResult tresult = resultSelector(item, score);
userScoreViewModel2List.Add(tresult);
}
}
}
return userScoreViewModel2List;
}最后这个还想说一点,我们使用通用的selectMany方法,并没有使用反射,而是通过外面传递的lamdba表达式,也就是外面传递的方法来实现这个通用的功能,从这里也可以看出来通过方法传递来实现一个功能是非常灵活的,可以写出很通用的代码。
当然我们这里是解析的集合,而不是解析的sql语句,如果是解析sql语句我们这里应该就是传递的表达式树了,ef中解析sql语句的selectMany原理后面有机会在说
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)