【发布时间】:2014-03-05 21:09:30
【问题描述】:
给定以下源数据:
Dim inputs = {New With {.Name="Bob", .Date="201405030500"},
New With {.Name="Sally", .Date="201412302330"},
New With {.Name="Invalid", .Date="201430300000"}}
我编写了以下 LINQ 查询(目的是在 Select 之前添加一个 Where success 子句作为过滤器,但我已将其省略并在结果中包含 success 以进行调试) :
Dim result1 = From i in inputs
Let newDate = New DateTime
Let success = DateTime.TryParseExact(i.Date, "yyyyMMddHHmm", Globalization.CultureInfo.InvariantCulture, Globalization.DateTimeStyles.AssumeLocal, newDate)
Select New With {
.Name = i.Name,
.Success = success,
.Date = newDate
}
但是,我得到以下结果,newDate 没有被 TryParseExact 填充:
因此,我重构了查询以将TryParseExact 提取到匿名方法中以获取以下内容:
Dim parseDate = Function(d As String)
Dim parsedDate As DateTime
Return New Tuple(Of Boolean, Date)(DateTime.TryParseExact(d, "yyyyMMddHHmm", Globalization.CultureInfo.InvariantCulture, Globalization.DateTimeStyles.AssumeLocal, parsedDate), parsedDate)
End Function
Dim result2 = From i in inputs
Let parsedDate = parseDate(i.Date)
Select New With {
.Name = i.Name,
.Success = parsedDate.Item1,
.Date = parsedDate.Item2
}
...这正确地给了我:
但是,我想找到一种完全在 LINQ 语句中执行此操作的方法,而无需使用匿名方法来创建元组。当然,我有一些可行的方法,但我想将其作为学术兴趣点。
我怀疑这是可能的,但我的问题是:
为什么result1 查询没有正确设置newDate 的解析日期?
(我考虑过惰性求值,但我认为它不适用于这里。)
更新:
- 感谢Hamlet 向我展示了您实际上可以同时声明和调用匿名方法!头脑 = 吹!
- 感谢Jim 建议使用 Nullable 而不是 Tuple!很有道理。
- 感谢 Ahmad 建议关闭,这对我来说肯定比匿名方法更干净。
由于下面的答案,我将 LINQ 重构如下(包括Where 子句过滤器):
Dim result3 = From i in inputs
Let parsedDate = Function(d)
Dim dtParsed As DateTime
Return If(DateTime.TryParseExact(d, "yyyyMMddHHmm", Globalization.CultureInfo.InvariantCulture, Globalization.DateTimeStyles.AssumeLocal, dtParsed), dtParsed, New DateTime?)
End Function(i.Date)
Where parsedDate.HasValue
Select New With {
.Name = i.Name,
.Date = parsedDate.Value
}
这实现了我正在寻找的东西,并且我相信编译器会优化生成的代码,但我仍然想确切地了解为什么 result1 不起作用。也许这是 Eric Lippert 或 John Skeet 的问题。
【问题讨论】: