委托
定义委托
关键字:delegate(自定义委托),Action(无返回值委托),Func(有返回值委托)
跟类(class)是平行的关系,不过也可以声明在类中,不过尽量不要声明在类中,委托是方法的类型,委托可以有参数可以有返回类型,但必须与所赋值的方法一致
D1 d1 = F1;//将d1委托指向F1方法
d1();//调用d1指向的方法
d1 = F2;//
d1();//将d1委托指向F2方法
D2 d2 = Add;
d2(1,2);
void F1()
{
Console.WriteLine("我是F1");
}
void F2()
{
Console.WriteLine("我是F2");
}
int Add(int i1,int i2)
{
return i1+i2;
}
delegate void D1();//声明无参数,返回值是void的委托D1
delegate int D2(int i1,int i2);//声明有参数有返回值的委托D2
一般情况下不会自定义泛型,而是利用微软自带的Action或Func来定义泛型,其中,Func定义委托时,最后一个参数为返回类型,后方的则是形参的类型,如下方的例子Func
Action d1 = F1;
d1();
d1 = F2;
d1();
Func<int,int,string> d2 = Add;
Console.WriteLine(d2(5,6));
void F1()
{
Console.WriteLine("我是F1");
}
void F2()
{
Console.WriteLine("我是F2");
}
string Add(int i1,int i2)
{
return (i1+i2).ToString();
}
匿名方法
指的是没有名字的方法,
Action d1 = delegate ()
{
Console.WriteLine("我是匿名方法");
};
d1();
Action<string,int> d2 = delegate (string x, int y)
{
Console.WriteLine($"字符串{x}与整型{y}");
};
d2("字符串",50);
Func<int, int, int> d3 = delegate (int a, int b)
{
return a + b;
};
Console.WriteLine(d3(5,6));
Lambda
Func<int, int, int> d4 = (int a, int b) =>
{
return a + b;
};
Console.WriteLine(d4(9, 6));
//也可以不写参数类型,编译器会自动判断参数类型
Func<int, int, int> d5 = (a, b) =>
{
return a + b;
};
Console.WriteLine(d5(9, 6));
//无返回值只有一行代码,可以省略{}
Action d11 = () => Console.WriteLine("我是lambda");
d11();
Action<string> d12 = (ddd) => Console.WriteLine(ddd);
d12("我是lambda2");
//有返回值,只有一行代码,可以省略return与{},return与{}必须同时省略
Func<string, string> d13 = (ddd) => $"我是有返回值有参数{ddd}";
Console.WriteLine(d13("lambda"));
//如果只有一个参数,()也可以省略
Func<string,string> d14 = ddd => $"我是有返回值有参数且只有一个参数的{ddd}";
Console.WriteLine(d14("lambda"));
LINQ
自己写一个Where方法
例子中,要查找出ints数组中符合条件的数据,调用方法直接传入数组与委托达到效果
int[] ints = new int[] { 10,20,30,1,2,5,6,99,8,10,3};
var ddd = MyWhere2(ints,b => b>10);
foreach (var i in ddd)
{
Console.WriteLine(i);
}
IEnumerable<int> MyWhere1(IEnumerable<int> a, Func<int, bool> b)
{
List<int> intlist = new List<int>();
foreach (int i in a)
{
if (b(i))
intlist.Add(i);
}
return intlist;
}
//简化版本
IEnumerable<int> MyWhere2(IEnumerable<int> a,Func<int,bool> b)
{
foreach (int i in a)
{
if(b(i))
yield return i;
}
}
常用扩展方法
List<Employee> lis = new List<Employee>();
lis.Add(new Employee { Id = 1, Name = "jerry", Age = 28, Gender = true, Salary = 5000 });
lis.Add(new Employee { Id = 2, Name = "jim", Age = 33, Gender = true, Salary = 3000 });
lis.Add(new Employee { Id = 3, Name = "lily", Age = 35, Gender = false, Salary = 9000 });
lis.Add(new Employee { Id = 4, Name = "lucy", Age = 16, Gender = false, Salary = 2000 });
lis.Add(new Employee { Id = 5, Name = "kimi", Age = 25, Gender = true, Salary = 1000 });
lis.Add(new Employee { Id = 6, Name = "nancy", Age = 33, Gender = false, Salary = 8000 });
lis.Add(new Employee { Id = 7, Name = "zack", Age = 31, Gender = true, Salary = 8500 });
lis.Add(new Employee { Id = 8, Name = "jack", Age = 38, Gender = true, Salary = 8000 });
class Employee
{
public long Id { get; set; }
public string? Name { get; set; }
public int Age { get; set; }
public bool Gender { get; set; }
public int Salary { get; set; }
public override string ToString()
{
return
$"Id={Id},Name={Name},Age={Age},Gender={Gender},Salary={Salary}";
}
}
Where
查询(取出)符合条件的结果,返回的是集合IEnumerable
IEnumerable<Employee> items1 = lis.Where(e=>e.Age >30);
foreach (var ddd in items1)
{
Console.WriteLine(ddd);
}
Count
注意区别Count属性与Count()方法,统计数据的条数,也可以输入条件统计符合条件的数据条数,返回的是行数int
如果查询的数据行数较多,超过了int类型的最大值,可以使用LongCount方法,这样返回值就会是long类型,LongCount与Count使用方法一样
lis.Count();//统计总数据行数
lis.Count(e=>e.Salary <5000);//统计工资小于5000的数据行数
Console.WriteLine(lis.Count(e=>e.Salary <5000 && e.Gender == true));//可以写的更复杂
lis.LongCount(e=>e.Age>10);
Any
判断集合中是否至少有一条数据满足要求,如果没有传入参数,则只判断集合是否至少有一条数据,返回的是bool类型的数据,与Count相比,Any是查找到一条符合条件的数据就返回了,Count则会遍历所有的数据,所以在只需要判断是否至少有一条数据符合条件时,用Any效率会更高
lis.Any();//判断集合是否至少有一条数据
lis.Any(e=> e.Salary>10000);//判断是否至少有一条数据工资大于10000
获取一条数据
- Single:如果确认有且只有一条满足要求的数据,那么就用Single方法。如果没有满足条件的数据或者满足条件的数据多与一条,Single方法就会抛出异常,有且只有一条的话,就会返回该条符合条件的数据,返回的是IEnumerable
类型的数据。 - SingleOrDefault:用法与Single类似,如果数据多于一条,就会抛出异常,不同的是,如果少于一条,就会返回类型的默认值。
- First:如果满足条件的数据有一条或多条,First方法就会返回第一条数据,如果没有满足条件的数据,就会抛出异常。
- FirstOrDefault:用法与First方法类似,不同的是,如果没有满足条件的数据,就会返回类型的默认值。 ```csharp lis.Single(e=>e.Name == “jerry”);//获取姓名等于jerry的数据
int[] ddd = new int[] { 1, 2, 3, 4, 5, 6 }; int dd = ddd.SingleOrDefault(e=>e >10);//返回int的默认值0
lis.First(e=> e.Age>30);//查询第一条年龄大于30的数据
Console.WriteLine(lis.FirstOrDefault(e=> e.Age>90));//返回默认值 ```