在函數式編程中,可以把函數看作數據。函數也可以作為參數,函數還可以返回函數。比如,LINQ就是基於函數式編程的。
語句式編程可能這樣寫:
string result;
if(value > 0)
{
result = "正數";
}
else
{
result = "負數";
}
而使用函數式表達式,可以簡化為:
var result = value > 0 "正數":"負數";
再來看一個過濾和排序的例子:
var i = 0;
while(i < list.Count)
{
if(list[i] % 2 != 0)
{
list.RemoveAt(i);
}
else
{
++i;
}
}
list.Sort();
函數式編程可以寫成如下:
from x in list
where x % 2 == 0
orderby x
select x;
或
list
.where(x => x % 2 == 0)
.OrderBy(x => x)
可見,在LINQ中,一個表達式(函數)的返回結果作為令一個表達式(函數)的源,還可以進行多個鏈式。
比如讀取遠程數據。
void Main()
{
XDocument timeDoc;
using(var client = new System.Net.WebClient())
{
timeDoc = XDocument.Parse(client.DonwloadString(""));
}
var ms = Convert.ToInt64(timeDoc.Root.Attribute("time").Value) / 1000;
var currentTime = new DateTime(1977,1,1).AddMilliseconds(ms).ToLocalTime();
Console.WriteLine(currentTime);
}
對於using部分我們可以提煉出一個方法。
private XDocument GetTime()
{
using(var client = new System.Net.WebClient())
{
return XDocument.Parse(client.DonwloadString(""));
}
}
void Main()
{
var timeDoc = GetTime();
var ms = Convert.ToInt64(timeDoc.Root.Attribute("time").Value) / 1000;
var currentTime = new DateTime(1977,1,1).AddMilliseconds(ms).ToLocalTime();
Console.WriteLine(currentTime);
}
但,還不夠。以上的GetTime方法只是對WebClient這個實現了IDisposable接口的using語句進行了封裝,可不可以對所有實現IDisposable接口的類型的using語句進行封裝呢?
public static class MyDisposable
{
public static TResult Using<TDisposable, TResult>(
Func<TDisposable> factory,
Func<TDisposable, TResult> map)
where TDisposable : IDisposable
{
using(var disposable = factory())
{
return map(disposable);
}
}
}
void Main()
{
var time = MyDisposable
.Using(
() => new System.Net.WebClient(),
client => XDocument.Parse(client.DownloadString(""))
)
.Root
.Attribute("time")
.Value;
var ms = Convert.ToInt64(time) / 1000;
var currentTime = new DateTime().AddMilliseconds(ms).ToLocalTime();
Console.WriteLine(currentTime);
}
在函數式編程中,函數返回的類型基本上另外一個函數方法的源實例。