從 Comparison/Converter 到Func 的進化
本篇文章給大家介紹兩個在.net2.0 中就已經出現的, 很"老"的委托方式.
通常情況下, 我們在Array 和 List<T> 類中使用這些功能. 明白用法和作用可以幫助你自如的使用它們.
但是你也可以使用和它們作用相同的Func 家族的形式 -- 在.NET 2.0 之后引入的新功能.
通過了解這些基本信息可以幫助我們看到一部分.net 進化的過程. 我稱這種內容為"歷史".
只是拋磚引玉, 希望大家多多交流
Comparison<T>
它的出現是為了對Array 和 List<T> 執行type-safe 排序.
注意, Linq函數的 OrderBy(), ThenBy() 是不支持comparison<T>委托的.
看下面的實例:
using System;
using System.Collections.Generic;
using System.Linq;
public class Hero
{
public string Name { get; set; }
public int Age { get; set; }
public double Power { get; set; }
}
class Program
{
static void Main(string[] args)
{
var heroes = new List<Hero>
{
new Hero {Name = "Goku", Age = 60, Power = 1000.00},
new Hero {Name = "Vegeta", Age = 65, Power = 800.00},
new Hero {Name = "Ikki", Age = 22,Power = 345.30},
new Hero {Name = "Dr. Slump", Age = 40, Power = 1.23},
};
Console.WriteLine("***** sort by age ****");
heroes.Sort((lhs, rhs) => Comparer<int>.Default.Compare(lhs.Age, rhs.Age));
Print(heroes);
Console.WriteLine("***** sort by name ****");
heroes.Sort((lhs, rhs) => string.Compare(lhs.Name, rhs.Name));
Print(heroes);
Console.WriteLine("***** sort by power ****");
heroes.Sort((lhs, rhs) => Comparer<double>.Default.Compare(rhs.Power, lhs.Power));
Print(heroes);
Console.Read();
}
private static void Print(IEnumerable<Hero> heroes)
{
foreach (var hero in heroes)
{
Console.WriteLine(hero.Name + "(" + hero.Age + ")");
}
}
很容易理解上面幾種排序的方法. 那么使用新的Func時, 實現如下:
Console.WriteLine("***** sort by name(Func) ****");
var heroesOrderByName = heroes.OrderBy(t => t.Name);
Print(heroesOrderByName);
Converter<TInput, TOutput>
Converter的使用是對某種類型的列表或者數組進行操作, 將其轉化為另外一個類型的列表或者數組.
繼續使用上面的代碼, 插入:
Console.WriteLine("***** TestFunc ****");
TestFunc(heroes);
Console.WriteLine("***** TestConverter ****");
TestConverter(heroes);
Console.WriteLine("***** TestLinqSelect ****");
TestLinqSelect(heroes);
private static void TestFunc(List<Hero> heroes)
{
Func<Hero, string> selector = p => p.Name;
IEnumerable<string> names = heroes.Select(selector);
print(names);
}
private static void TestLinqSelect(List<Hero> heroes)
{
var names = heroes.Select(p => p.Name);
print(names);
}
private static void TestConverter(List<Hero> heroes)
{
var names = heroes.ConvertAll(p => p.Name);
print(names);
}
private static void print(IEnumerable<string> names)
{
foreach (string name in names)
Console.WriteLine(name);
}
其實上面 TestLinqSelect 和 TestFunc 是同一碼事, 我只是給大家提供不同的代碼方案而已. 一般, 我們不會使用TestFunc 這種形式.
注意, 用 Linq 的Select 和其他一些Linq的函數一樣, 是推遲執行, 這意味著, 很多時候, 它們將不執行轉換, 直到數值被使用.
這事實上是雙刃劍, 有時候它可以獲取更好的效率, 但是如果你馬上就想要結果就會導致額外的后臺工作開銷 -- 支持延遲執行的功能本身需要使用到yield return /yield break 來維持當前狀態的信息迭代器.
小結
本質上來講, Comparison/Converter 和與之相對應的Func沒有太多區別, 但是為什么.net 讓它們同時存在, 或者換句話講在有了實現方案后, 為什么要"多余"引入后者?
這是因為之后被引入的委托Func<>是一個多功能兵種, 但是在執行具體任務的時候效果稍有區別.
在新項目中, 我們也更傾向于使用新的方法.
參考文章:C#/.NET Little Wonders: The Predicate, Comparison, and Converter Generic Delegates
本文來自于喜樂的ASP.NET(Alex Song) 轉貼請注明出處

浙公網安備 33010602011771號