考慮下面的源數據中使用DateTime.TryParseExact:如何在LINQ聲明
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語句中完全執行此操作,而不需要nee d使用匿名方法創建一個元組。當然,我已經有了一些可行的方法,但我希望將其作爲學術興趣點。
我懷疑這是可能的,但我的問題是:
爲什麼不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的問題。
感謝您回答我關於上面評論中的「Let'子句的問題,以及向TryParsers庫介紹我。這看起來好多了。 – MCattle
你可能要考慮檢查'.Success = Not d.HasValue()'而不是'Not d Is Nothing' –
@JimWooley沒有任何區別 – hazzik