2012-09-09 68 views
2

代碼假設你通過3個元素這樣想循環:執行之間的循環迭代

for(int i=0; i<3; i++) 
{ 
    doSomething(); 
} 

當然,這是相同的話說:doSomething(); doSomething(); doSomething();

現在,讓我們說你想要做的事每個迭代之間,如如果你是這樣的編碼: doSomething(); doBetween(); doSomething(); doBetween(); doSomething();

通知doSomething()是如何被調用的3倍,但doBetween()被稱爲2倍。

現在,我知道如何在一個循環做到這一點的唯一方法是:

for(int i=0; i<3; i++) 
{ 
    doSomething(); 
    if(i<2) 
     doBetween(); 
} 

對我來說,這似乎低效運行一個循環內的條件。它也使你必須看兩遍才能理解編程意圖。此外,如果您將「3」更改爲「for」標題中的其他內容,則可能很容易忘記更改條件,特別是隨着邏輯的增長。不僅如此,這個技巧在foreach循環中不起作用,因爲沒有簡單的方法來檢測我們是否正在運行最後一次迭代。

你有什麼祕訣可以讓你獲得更好的性能,更好的可讀性,更好的可維護性或者在foreach循環中嗎?

+0

這讓我想知道是否有任何編程語言有明確的語法來在這樣的循環迭代之間運行代碼塊。我認爲用類似C的語言,它可能類似於{...}之間的(for)(whatever){...} 當然,for也可以是while或foreach '。 (並且會出現一個懸而未決的問題,就像懸掛的其他問題一樣) – Stewart

回答

1

你總是可以編寫一個可重複使用的功能,不知道這會是一個好主意,除非你需要重用這個有很多

public static IEnumerable<TSource> ForEach<TSource>(this System.Collections.Generic.IEnumerable<TSource> source, Action<TSource> action, Action<TSource> between) 
    { 
     bool first = true; 
     foreach (TSource item in source) 
     { 
      if (first) first = false; else between(); 
      action(item); 
     } 
     return source; 
    } 

這被稱爲像這樣:

myList.ForEach(i => DoSomething(), i => DoBetween()); 

或者

Enumerable.Range(0, 3).ForEach(i => DoSomething(), i => DoBetween()); 
+0

我喜歡這個答案最好。這是目前唯一的答案,使調用代碼更易於閱讀,維護風險更小。它使foreach能夠被使用。 – hgarland

+0

@hgarland謝謝:-)我發現這個ForEach函數在其更簡單的形式中是非常有用的,沒有'之間'參數。我在linq中使用了很多。我也有一個重載索引傳遞給正在迭代的項目,這通常很有用。 – MikeKulls

3
for(int i = 0; i < 3; i++) { 
    if(i > 0) { 
     doBetween(); 
    } 
    doSomething(); 
} 
+2

這是一個非常明確的說法。 –

+0

@TimSchmelter:這幾乎是一樣的。他很可能根本不想在第一個或最後一個元素之前調用它。 – ThiefMaster

3

那麼簡單的事情呢?

for(int i = 0; i < 3; i++) { 
    doSomething(); 
    doBetween(); 
} 
doSomething(); 
+0

這將適用於所提供的代碼,但假設他正在迭代一個列表(因此是foreach引用),這不會很好。 –

+1

我看到的問題是「doSomething」是重複代碼。儘管這是一個小的重複,但如果doSomething的調用發生變化,則需要在2個地方進行更改。 – MikeKulls

+1

另外,正如有人在下面指出的那樣,您需要額外的檢查以確保被迭代的列表不是空的。然後還有其他問題將我(或正在迭代的項目)傳遞給doSomething – MikeKulls

1

假設你想「DoSomething的」和「doBetween」上無論你在foreach迭代:

bool firstComplete = false; 

foreach(Item i in ItemList) 
{ 
    if (firstComplete) 
    { 
     doBewteen(i); 
    } 
    else 
    { 
     firstComplete = true; 
    } 

    doSomething(i); 
} 
+0

這相當醜陋.. – ThiefMaster

+0

@ThiefMaster對我來說很好看 – MikeKulls

+0

@JTorres它看起來很好,現在看起來對我來說過於冗長了。 – MikeKulls

0

沒有內建了對的事情。你可以做你自己的自定義枚舉器,它可以調用其中的某個枚舉器,但是它只是稱爲它而已。

無論你如何解決它,你都無法繞過每次迭代的檢查。像這樣簡單的檢查幾乎不會損害表現。

我通常使用一個布爾標誌是:

bool first = true; 
for (int i = 0; i < 3; i++) { 
    if (first) { 
    first = false; 
    } else { 
    doBetween(); 
    } 
    doSomething(); 
} 

你也可以考慮將一個迭代圈外:

doSomething(); 
for (int i = 1; i < 3; i++) { 
    doBetween(); 
    doSomething(); 
} 

但是,如果循環可能永遠是空的(零項目),你將不得不首先檢查。

0

這將允許您在進入循環之前定義開始和結束點...

int start = 0; 
int limit = 3; 
for (int i == start; i < limit; i++) { 
    doSomething(); 
    if (i > start && i < limit - 1) { 
     doBetween(); 
    } 
}