这是一个奇怪的问题,但是有一天它出现了,它让我思考。
什么时候最好使用这种形式的lambda表达式设计“。(x => x.Whatever)”verse“。(()=> obj.Whatever)”。
考虑以下扩展方法。
public static class ExtensionMethods
{
public static string TryToGetTheString<T>(this T value, Func<T, string> method)
{
try
{
return method(value);
}
catch (Exception)
{
return "banana";
}
}
public static string TryToGetTheStringTwo<T>(this T value, Func<string> method)
{
try
{
return method();
}
catch (Exception)
{
return "banana";
}
}
}
以下自我引用类。
public class testClass5000
{
private int? _id;
public int? ID { get { return _id; } set { _id = value; } }
private string _urgh;
public string Urgh { get; set; }
public testClass5000 tc5k { get; set; }
}
然后使用极其惰性的进程来避免检查空值,在尝试从testClass5000获取字符串(Urgh)时,您可以实现类似的扩展方法和类,
private void main()
{
var tc = new testClass5000();
textBox1.text = tc.TryToGetTheString(x => x.tc5k.tc5k.tc5k.Urgh);
}
但是,由于tc是在本地声明的,因此也可以使用。
private void main()
{
var tc = new testClass5000();
textBox1.text = tc.TryToGetTheStringTwo(() => tc.tc5k.tc5k.tc5k.Urgh);
}
我很好奇,(x => x.tc5k.tc5k.tc5k.Urgh)
是必要的,而(() => tc.tc5k.tc5k.tc5k.Urgh)
更可取。
//////////////////////////////////////////
我确实提出了以下场景,其中传递参数似乎更合适。
使用以下扩展方法。
public static class ExtensionMethods
{
public static T TestOne<T>(this T value, Func<T, T> method)
{
try
{
return method(value);
}
catch (Exception)
{
return default(T);
}
}
public static T TestTwo<T>(this T value, Func<T> method)
{
try
{
return method();
}
catch (Exception)
{
return default(T);
}
}
}
并使用以下代码。
private void Form1_Load(object sender, EventArgs e)
{
var firstValue = 5;
var secondValue = 10;
var resultOne = firstValue.TestOne(x => x + 1).TestOne(x => x * 2);
//returns 12
var resultTwo = secondValue.TestTwo(() => secondValue + 1).TestTwo(() => secondValue * 2);
//returns 20
var resultThree = secondValue.TestTwo(() => secondValue.TestTwo(() => secondValue + 1) * 2);
//returns 22
}
在此示例中.TestOne(x =&gt; x + 1).TestOne(x =&gt; x * 2)是首选符号,因为要在不通过参数的情况下实现相同的操作,您需要开始嵌套表达式。
答案 0 :(得分:4)
直接在lambda中注入参数值的成本更高,因为编译器必须为此目的创建一个特殊的类。
如果我们排除性能考虑因素,那么我会说注入参数更容易编写(这里是个人偏好),并且保持原型中的参数((x,y)=&gt; //做某事)是有用的当你实际上不是提供参数值的那个。例如,使用Select Linq查询时。或者我经常将它用于负载平衡场景(lambda“service =&gt; service.SomeFunction()”,然后是特殊工厂检索服务并执行lambda)。
答案 1 :(得分:3)
如果参数与您提供的原始值不完全相同。
粗略的例子
public static class Extensions
{
public static void DoSomething(this string s,Action<string> action)
{
var something = Enumerable.Range(1,100).Select(i=> String.Format("{0}_{1}",s,i));
foreach (var ss in something)
{
action(ss);
}
}
}
然后
var something = "ABC123";
something.DoSomething(x=>Console.WriteLine(x));
//Ignoring that we could do something.DoSomething(Console.WriteLine);
显然,如果没有这个参数,你就无法获得你所感兴趣的实际值,原始值在这个概念中是没有用的。