提起函數式編程,大家一定想到的是語法高度靈活和動態的LISP,Haskell這樣古老的函數式語言,往近了說ruby,javascript,F#也是函數式編程的流行語言。然而自從.net支持了lambda表達式,C#雖然作為一種指令式程序設計語言,在函數式編程方面也毫不遜色。我們在使用c#編寫代碼的過程中,有意無意的都會使用高階函數,組合函數,純函數緩存等思想,連表達式樹這樣的idea也來自函數式編程思想。所以接下來我們把常用的函數式編程場景做個總結,有利於我們在程序設計過程中靈活應用這些技術,拓展我們的設計思路和提高代碼質量。
一、高階函數
高階函數通俗的來講:某個函數中使用了函數作為參數,這樣的函數就稱為高階函數。根據這樣的定義,.net中大量使用的LINQ表達式,Where,Select,SelectMany,First等方法都屬於高階函數,那麼我們在自己寫代碼的時候什麼時候會用到這種設計?
舉例:設計一個計算物業費的函數,var fee=square*price, 而面積(square)根據物業性質的不同,計算方式也不同。民用住宅,商業住宅等需要乘以不同的系數,根據這樣的需求我們試著設計下面的函數:
民用住宅面積:
public Func SquareForCivil()
{
return (width,hight)=>width*hight;
}
商業住宅面積:
public Func SquareForBusiness()
{
return (width, hight) => width * hight*1.2m;
}
這些函數都有共同的簽名:Func,所以我們可以利用這個函數簽名設計出計算物業費的函數:
public decimal PropertyFee(decimal price,int width,int hight, Func square)
{
return price*square(width, hight);
}
是不是很easy,寫個測試看看
[Test]
public void Should_calculate_propertyFee_for_two_area()
{
//Arrange
var calculator = new PropertyFeeCalculator();
//Act
var feeForBusiness= calculator.PropertyFee(2m,2, 2, calculator.SquareForBusiness());
var feeForCivil = calculator.PropertyFee(1m, 2, 2, calculator.SquareForCivil());
//Assert
feeForBusiness.Should().Be(9.6m);
feeForCivil.Should().Be(4m);
}
二、惰性求值
C#在執行過程使用嚴格求值策略,所謂嚴格求值是指參數在傳遞給函數之前求值。這個解釋是不是還是有點不夠清楚?我們看個場景:有一個任務需要執行,要求當前內存使用率小於80%,並且上一步計算的結果
我們可以很快寫出符合這個要求的C#代碼:
public double MemoryUtilization()
{
//計算目前內存使用率
var pcInfo = new ComputerInfo();
var usedMem = pcInfo.TotalPhysicalMemory - pcInfo.AvailablePhysicalMemory;
return (double)(usedMem / Convert.ToDecimal(pcInfo.TotalPhysicalMemory));
}
public int BigCalculatationForFirstStep()
{
//第一步運算
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine("big calulation");
FirstStepExecuted = true;
return 10;
}
public void NextStep(double memoryUtilization,int firstStepDistance)
{
//下一步運算
if(memoryUtilization
{
注:更多精彩教程請關注三聯網頁設計教程 欄目,