我遇到了一段我无法弄清楚的代码,甚至可能无效。您可以在下面找到代码。
方法GetDataTableData()
返回System.Data.DataTable
方法Select(...)
返回DataRow对象数组:DataRow[] rows
。据我所知,Select()中的lambda无效。
var table = GetDataTableData()
.Select(s => new { s.Index })
.AsEnumerable()
.Select(
(s, counter) => new { s.Index, counter = counter + 1 }
);
方法Select(...)
有几个重载,都以类型字符串开头。
这里有上面提到的行
// of what type is this (a delegate?)
s => new { s.Index }
...
// and what does this
(s, counter) => new { s.Index, counter = counter + 1 }
据我所知,至少第二个Select引用了IEnumerable.Select<T>
。但是对集合调用AsEnumerable()
并不会改变基础类型:
// calling AsEnumberable() does not change type
IEnumerable<DataRow> enumDataRows = GetDataTable().AsEnumerable();
Type type = enumDataRows.GetType().GetGenericArguments()[0];
type.Dump(); // still returns DataRow
因此,属性Index必须存在于lambda表达式(s) => { return new { s.Index }; }
的基础类型中才能工作。
这个假设是否正确?
我如何识别它是Select()
中的内置版本或可枚举方法Enumerable.Select<TSource, TResult>
尽管如此,我认为该语句仍然无效,因为tSource底层对象DataRow没有属性Index
:
var tResult = GetDataTable().Select(
(tSource, tResult) => { return new { tSource.Index }; }
);
这个假设是否正确?
答案 0 :(得分:2)
您使用的Select
为IEnumerable.Select<T>
,因为AsEnumerable()的返回值为IEnumerable<T>
。
答案 1 :(得分:1)
两者都是导致匿名对象的lambda。此外,两者都是以非常简洁的形式编写的,完整的表格将是:
(s) => { return new { s.Index }; }
第二个是等效的。
两个lambdas都是Func<>
个代表,具有不同的签名。
lambda可以产生一个字符串,但这取决于你使用它的方式(类型推断在这里是一个很大的事情,而且lambdas非常简洁的原因之一)。
lambda的返回类型取决于您使用它的上下文 - 它可以是委托,但在您的情况下,它不是。 lambda是一个委托 - 如果它有一个返回类型,它是Func<T1, T2, ... Tn, TReturn>
,如果没有,它是Action<T1,T2,..., Tn>
。