函数作为返回值
就像常见的函数一样,Lambda 表达式可以返回一个函数指针(委托实例)。这就意味着我们能够使用一个 Lambda 表达式来创建并返回另一个 Lambda 表达式。这种行为在很多场景下都是非常有用的。我们先来看下面这个例子:
1 Func<string, string> SayMyName(string language) 2 { 3 switch (language.ToLower()) 4 { 5 case "fr": 6 return name => 7 { 8 return "Je m'appelle " + name + "."; 9 }; 10 case "de": 11 return name => 12 { 13 return "Mein Name ist " + name + "."; 14 }; 15 default: 16 return name => 17 { 18 return "My name is " + name + "."; 19 }; 20 } 21 } 22 23 void Main() 24 { 25 var lang = "de"; 26 //Get language - e.g. by current OS settings 27 var smn = SayMyName(lang); 28 var name = Console.ReadLine(); 29 var sentence = smn(name); 30 Console.WriteLine(sentence); 31 }
这段代码可以写的更简洁些。如果请求的语言类型未找到,我们可以直接抛出一个异 常,以此来避免返回一个默认值。当然,出于演示的目的,这个例子展示了类似于一种函数工厂。另外一种方式是引入 Hashtable ,或者更好的 Dictionary<K, V> 类型。
1 static class Translations 2 { 3 static readonly Dictionary<string, Func<string, string>> smnFunctions 4 = new Dictionary<string, Func<string, string>>(); 5 6 static Translations() 7 { 8 smnFunctions.Add("fr", name => "Je m'appelle " + name + "."); 9 smnFunctions.Add("de", name => "Mein Name ist " + name + "."); 10 smnFunctions.Add("en", name => "My name is " + name + "."); 11 } 12 13 public static Func<string, string> GetSayMyName(string language) 14 { 15 //Check if the language is available has been omitted on purpose 16 return smnFunctions[language]; 17 } 18 } 19 20 // Now it is sufficient to call Translations.GetSayMyName("de") 21 // to get the function with the German translation.
尽管这看起来有点过度设计之嫌,但毕竟这种方式很容易扩展,并且可以应用到很多场景下。如果结合反射一起使用,可以使程序变得更灵活,易于维护,并且更健壮。下面展示了这个模式如何工作: