一、Lambda表达式
1.描述
Lambda表达式由一个左部(表示输入参数)、=>符号以及一个右部(表示需要求值的表达式)组成。
【示例】
using System;
namespace 简单的Lambda表达式
{
class Program
{
//Lambda表达式省略了delegate关键字、函数头、参数类型、方括号以及return关键字
//Lambda表达式就是一个简洁的委托。左侧(相对于运算符“=>”而言)代表函数的参数,而右侧是函数主体
delegate void FunctionPointer(string str);
static void Main(string[] args)
{
FunctionPointer fp =
s => Console.WriteLine(s);
fp("Hello World");
Console.ReadLine();
}
}
}
2.搜索字符串
泛型委托Predicate接受一个由T指定的参数并返回一个布尔值。Predicate用在诸如Array.Find和Array.FindAll这样的函数中。Predicate可以通过普通函数、匿名委托或是Lambda表达式来初始化。
【示例】
using System;
using System.Linq;
namespace 搜索字符串
{
class Program
{
static void Main(string[] args)
{
//通过匿名类型和数组初始化器创建一个people数组
var people = new[]
{
"xu shuai","zhu xiao",
"wang feng","xu tao",
"hu xiang","bian jingbin","wang rui"
};
//Lambda表达式
//Where:基于谓词筛选值序列
var results = people.Where(
s => s.Contains("xu"));
Console.WriteLine("/*显示含有某个关键字的字符串*/");
Array.ForEach<string>(results.ToArray<string>(), s => Console.WriteLine(s));
//Predicate:泛型委托,用于定义一组条件并确定参数是否符合这些条件。
Predicate<string> match = s => s.Contains("g");
var ss = people.ToList<string>().FindAll(match);
Console.WriteLine("/*使用list<T>的FindAll以及由Lambda表达式初始化的Predicate*/");
Array.ForEach<string>(ss.ToArray<string>(), s => Console.WriteLine(s));
Console.ReadKey();
}
}
}
3.从序列中获取特定元素
using System;
using System.Linq;
namespace 从序列中获取特定元素
{
class Program
{
static void Main(string[] args)
{
var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
//first
var first = (from n in numbers select n).First();
Console.WriteLine("数组的第一个数:{0}", first);
var firstOrDefault = (from n in numbers select n).FirstOrDefault(n => n > 3);
var firstOrDefault1 = (from n in numbers select n).FirstOrDefault(n => n > 10);
Console.WriteLine("First or Default: {0}", firstOrDefault);
Console.WriteLine("First or Default: {0}", firstOrDefault1);
//single
var single = (from n in numbers where n == 2 select n).Single();
Console.WriteLine("Single: {0}", single);
var singleOrDefault = (from n in numbers select n).SingleOrDefault(n => n == 2);
Console.WriteLine("Single or Default: {0}", singleOrDefault);
var singleOrDefault1 = (from n in numbers select n).SingleOrDefault(n => n == 20);
Console.WriteLine("Single or Default: {0}", singleOrDefault1);
//elment at
var element = (from n in numbers select n).ElementAt(2);
Console.WriteLine("elementat: {0}", element);
var elementOrDefault = (from n in numbers select n).ElementAtOrDefault(11);
Console.WriteLine("Element at 11 or default: {0}", elementOrDefault);
var elementOrDefault1 = (from n in numbers select n).ElementAtOrDefault(8);
Console.WriteLine("Element at 11 or default: {0}", elementOrDefault1);
Console.ReadKey();
}
}
}
4.筛选信息
using System;
using System.Linq;
namespace 筛选信息
{
class Program
{
static void Main(string[] args)
{
var numbers = new int[] { 32, -2, 3, 43, 6, 14, -24, 8, 0 };
var result = from n in numbers where Math.Abs(n) > 20 select n;
foreach (var item in result)
{
Console.WriteLine(item);
}
var randomDate = new object[] { 1, 2, "two", "three", 5, "monday",34m };
var beInt = from i in randomDate.OfType<int>() select i;
var beString = from s in randomDate.OfType<string>() select s;
var beDecimal = from d in randomDate.OfType<decimal>() select d;
Console.WriteLine("整型数字:");
foreach (var item in beInt)
{
Console.WriteLine(item);
}
Console.WriteLine("字符串:");
foreach (var item in beString)
{
Console.WriteLine(item);
}
Console.WriteLine("deciaml类型:");
foreach (var item in beDecimal)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
}
5.使用Select和Lambda表达式
【示例】
using System;
using System.Linq;
namespace 使用Select和Lambda表达式
{
class Program
{
static void Main(string[] args)
{
var numbers = new int[] { 1, 3, 4, 54, 2, 32 };
//select返回的是一个IEnumerable<T>实例,其中T是Lambda表达式所返回的对象的类型
foreach (var item in numbers.Select(n=>n%2))
{
Console.WriteLine(item);
}
//通过命名初始化的方式将n投影为一个新的类型
foreach (var item in numbers.Select(n=>new {Number=n,isEven=n%2==0 }))
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
}
6.使用Where和Lambda表达式
using System;
using System.Collections.Generic;
using System.Linq;
namespace 使用Where和Lambda表达式
{
class Program
{
static void Main(string[] args)
{
var words = new string[] { "xushuai", "hahh", "xianggou", "jijisa" };
IEnumerable<string> hasX = words.Where(s => s.Contains("x"));
foreach (var item in hasX)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
}
7.使用OrderBy和Lambda表达式
【示例】
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 使用OrderBy和Lambda表达式
{
class Program
{
static void Main(string[] args)
{
var numbers = new int[] { 32, 43, 3, 2, 53, 47 };
Console.WriteLine("/*升序排序*/");
IEnumerable<int> orderDesc = numbers.OrderBy(n => n);
foreach (var item in orderDesc)
{
Console.WriteLine(item);
}
Console.WriteLine("/*降序排序*/");
IEnumerable<int> orderAsc = numbers.OrderByDescending(n => n);
foreach (var item in orderAsc)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
}
8.Lambda表达式和闭包
由于变量存在生命周期,换句话说,变量的作用域是有范围的。例如,当我们在一个函数中声明一个变量后,在函数执行完毕后,这个变量将从该函数的栈内存空间中清除掉。试想,如果我们在一个Lambda表达式中使用了本地变量的话,该本地变量将会在函数的栈空间清理的时候被移除。为了防止这样的糟心事发生,当一个依赖于本地变量的Lambda表达式需要从函数中返回出去,编译器就会创建一个闭包,即一个包装器类。
闭包是一个自动生成的类,它含有Lambda表达式,并为每个被用到的本地变量生成一个字段。这些本地变量的值会被复制到相应的字段中,以便扩展这些本地变量的生命周期。
闭包是一个自动生成的类,它含有Lambda表达式,并为每个被用到的本地变量生成一个字段。这些本地变量的值会被复制到相应的字段中,以便扩展这些本地变量的生命周期。
【示例】
using System;
using System.Collections.Generic;
using System.Linq;
namespace Lambda表达式和闭包
{
class Program
{
static void Main(string[] args)
{
UserClosur();
Console.ReadKey();
}
static void UserClosur()
{
string toFind = "ed";
var words = new string[]
{
"ended","experienced",
"friend","closed","hahah"
};
//使用本地变量toFind就会通知编译器生成一个闭包(或包装器类)
//这样,toFind就不会称为“未定义”的
var matches = words.Select(s => s.Contains(toFind));
foreach (var item in matches)
{
Console.WriteLine(item);
}
IEnumerable<string> hasED = words.Where(s => s.Contains("ed"));
foreach(string s in hasED)
{
Console.WriteLine(s);
}
}
}
}
三、柯里化
即将一个多步骤表达式拆分成多个Lambda表达式,每一个Lambda表达式都是下一个Lambda表达式的资源提供者,最后一个表达式所提供的就是整个解决方案
【示例】
using System;
namespace 柯里化
{
class Program
{
static void Main(string[] args)
{
Func<int, int, int> test1 = (x, y) => x + y;
Console.WriteLine(test1(4, 7));//11
Func<int, Func<int,int>> test2 = x => y => x + y;
Console.WriteLine(test2(4)(7));//11
Console.ReadKey();
}
}
}