标签:处理 区别 stat toc 语言 public 优点 lin c中
定义: 函数式编程(FP)是一种编程范式,强调函数的同时避免状态突变的编程风格.
简单讲,就是将函数当作值处理.
Func<int, int> triple = x => x * 3;
var range = Enumerable.Range(1, 3);
var triples = range.Select(triple);
triples //=>[3,6,9]
意思是: 一旦创建一个对象,便永远不会改变,且变量永远不会被重新赋值.
/********排序问题***************/
//函数式方法:
Func<int, bool> isOdd = x => x % 3==1;
int[] original = { 7, 6, 1 };
var sorted = original.OrderBy(x=>x);//排序 不会改变原有数据,而是创建一个新数据
var filtered = original.Where(isOdd);
//非函数式方法:
var original = new List<int>{ 7, 6, 1 };
original.Sort();//排序 会改变原有数据
大多数面向对象(oo)开发人员在其方法实现中严重依赖于命令式风格,使状态就地突变并使用显示控制流:他们在大规模的命令式编程中使用了OO设计.
也就是命令式与函数式区别.
函数式遵循原则:
总的来说,就是C#对函数式编程很好支持某些函数式技术,对部分支持不是很好在不断迭代中弥补.
最常见的操作:映射,排序和过滤.
具体示例:
Enumerable.Range(1, 100)
.Where(i => i % 20 == 0)
.OrderBy(i => -i)
.Select(i => $"{i}%");
// => ["100%","80%","60%","40%","20%",]
注意: Where,OrderBy,Select都接受函数作为参数,并且不会使给定的Enumerable突变,而是返回一个新的Enumerable.
与FP相关的C#6和C#7特性:
相关示例:
using System;
using static System.Math;//使用using static 导入静态变量
public class Circle
{
public double Radius { get; }
public double Circumference=> PI * 2 * Radius;//具有表达式体式成员的更简洁函数
public Circle(double radius)=> Radius = radius;//具有只读的自动属性的更简易不可变类型
public double Area
{
get
{
double Square(double d) => Pow(d, 2);//局部函数
return PI * Square(Radius);
}
}
public (double Circumference, double Area) Stats=> (Circumference, Area);//新特性-5.更加的元组语法
}
未来发展趋势:
四种表示函数的语言结构:
//
//实例化和使用委托
var list = Enumerable.Range(1, 10).Select(i => i * 3).ToList();
//list =>[3,6,9,12,15,18,21,24,27,30]
Comparison<int> alphabetically = (l, r)=> l.ToString().CompareTo(r.ToString());
list.Sort(alphabetically);
//list =>[12,15,18,21,24,27,3,30,6,9]
//用一个lambda声明一个函数内联
var list = Enumerable.Range(1, 10).Select(i => i * 3).ToList();
//list =>[3,6,9,12,15,18,21,24,27,30]
list.Sort((l, r) => l.ToString().CompareTo(r.ToString()));
//list =>[12,15,18,21,24,27,3,30,6,9]
/****************************************/
// lambda可访问封闭作用域内的变量
var days = Enum.GetValues(typeof(DayOfWeek)).Cast<DayOfWeek>();
// => [Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday]
IEnumerable<DayOfWeek> daysStartingWith(string pattern)
=> days.Where(d => d.ToString().ToLower().StartsWith(pattern.ToLower()));
daysStartingWith("s");
// => [Saturday,Sunday]
//
高阶函数(HOF):是接受其他函数作为输入或返回一个函数作为输出的函数,或两者兼而有之.
有些HOF接受其他函数作为参数并调用它们以完成工作,有点像公司可能将其工作分包给另一家公司.
// Where 理想化实现
//Where: 一个迭代应用给定谓词的典型HOF
//where方法负责排序逻辑,调用者提供谓词,这是基于该条件过滤IEnumerable的准则.
public static IEnumerable<T> Where<T>(this IEnumerable<T> ts, Func<T, bool> predicate)
{
foreach (T t in ts)
{
if (predicate(t))
yield return t;
}
}
//HOF(高阶函数)- 控制倒转
public class Cache<T> where T : class
{
public T Get(Guid id) => default(T);
//
public T Get(Guid id, Func<T> onMiss) => Get(id) ?? onMiss();
}
有些HOF根本不应用所给定的函数,而是返回一个新函数,以某种方式与给定的作为参数的函数相关.
static Func<T2, T1, R> SwapArgs<T1, T2, R>(this Func<T1, T2, R> f)=> (t2, t1) => f(t1, t2);
//执行整数除法函数
Func<int, int, int> divide = (x, y) => x / y;
divide(10, 2);//=> 5
var divideBy = divide.SwapArgs();
var tBy = divideBy(2,10);// => 5
有时会编写主要用于创建其他函数的函数--可将其视为函数工厂.
//使用lambda过滤数字序列 取偶数
var range = Enumerable.Range(1, 20);
range.Where(i => i % 2 == 0);
//=> [2,4,6,8,10,12,14,16,18,20]
//计算给定的书是否被n整除
Func<int, bool> isMod(int n) => i => i % n == 0;
Enumerable.Range(1, 20).Where(isMod(2));//=> [2,4,6,8,10,12,14,16,18,20]
Enumerable.Range(1, 20).Where(isMod(3));//=> [3,6,9,12,15,18]
HOF最常用的方式是封装安装和拆卸的操作.
编写一个函数来执行安装和拆卸,并将其间的操作参数化.
//连接数据库帮助类
public static class ConnectionHelper
{
//执行安装和拆卸
public static R Connect<R>(string connString, Func<IDbConnection, R> f)
{
//操作已被参数化,整个过程属于安装
using (var conn = new SqlConnection(connString))
{
conn.Open();
return f(conn);
}
//结束时,拆卸
}
}
using本身就是安装/拆卸例子,具体如下:
参考-广泛复用案例
public static class F
{
//应该在没有被using static所限定的情况下可用
public static R Using<TDisp, R>(TDisp disposable, Func<TDisp, R> f) where TDisp : IDisposable
{
using (disposable) return f(disposable);
}
}
然后,对第一点连接数据库帮助类改进
public static class ConnectionHelper_2
{
//应该在没有被using static所限定的情况下可用
public static R Connect<R>(string connStr, Func<IDbConnection, R> f)
=> F.Using(new SqlConnection(connStr), conn => { conn.Open(); return f(conn);});
}
HOF优势:
HOF缺陷:
注意:适时可使用HOF,但要注意可读性:使用简短的lambda表达式,清晰的命名以及有意义的缩进.
函数式编程优点:
标签:处理 区别 stat toc 语言 public 优点 lin c中
原文地址:https://www.cnblogs.com/mwc0315/p/14857066.html