小弟在練習迭代器時,碰上錯誤處理的問題想請教各位大大。
一開始發現錯誤沒有辦法正確被外層 catch 區塊捕捉,如下
static void Main(string[] args) {
try {
IEnumerable<int> a = null;
var b = DoNothing(a);
}
catch (Exception ex)
{ }
}
static IEnumerable<TSource> DoNothing<TSource>(IEnumerable<TSource> source) {
if(source == null) throw new ArgumentNullException();
using (var iterator = source.GetEnumerator()) {
while (iterator.MoveNext())
yield return iterator.Current;
}
}
無論我怎麼修改內容或重新建置,試了各種蠢方法,程式碼依然不會進到 catch 區塊,而是將錯誤內容放在變數 b 的結果檢視。
後來去找官方 Linq 的 source code,終於找到與我的程式碼不同處了,它型別檢查與錯誤拋出的方法是用 return 而不是 yield return,所以我把迭代器方法抽出,如下
static void Main(string[] args) {
try {
IEnumerable<int> a = null;
var b = DoNothing(a);
}
catch (Exception ex)
{ }
}
static IEnumerable<TSource> DoNothing<TSource>(IEnumerable<TSource> source) {
if(source == null) throw new ArgumentNullException();
return DoNothingIterator(source);
}
static IEnumerable<TSource> DoNothingIterator<TSource>(IEnumerable<TSource> source) {
using (var iterator = source.GetEnumerator()) {
while (iterator.MoveNext())
yield return iterator.Current;
}
}
發現拋出錯誤無法與 yield return 寫在一起,但我想搞清楚原因,所以上來發文求助,希望有大大能開導小弟。
發現拋出錯誤無法與 yield return 寫在一起
可以寫一起
終於找到與我的程式碼不同處了,它型別檢查與錯誤拋出的方法是用 return 而不是 yield return
因為IEnumerable + yield return 等於跟系統宣告說等我用到時在給我資料並執行
而你的問題就出在這,這個技術稱為 lazy evaluation 『意味著在迭代查詢結果之前,不會執行迭代』,假如只有return就不會使用lazy evaluation直接執行迭代。
最簡單迭代查詢結果方式,使用ToList或是ToArray,程式改成下面這樣就可以
static void Main(string[] args) {
try {
IEnumerable<int> a = null;
var b = DoNothing(a).ToList();
}
catch (Exception ex)
{ }
}