在foreach的判斷條件裡執行方法會有效率問題嗎?

weixin_34391854發表於2010-02-02

  樓豬平時一有空就有看別人程式碼的習慣,從許多優秀規範的程式碼中學習到了很多簡約高效的寫法和畫龍點睛的思想精華。但是有的時候也會覺得某些寫法很值得玩味。比如剛看到一段程式碼,在foreach的條件判斷里加了一個方法。樓豬一開始想當然地認為迴圈幾次,方法也會執行幾次,這樣肯定會有效率問題。但是看來看去還是不確定寫程式碼的人為什麼要這麼寫,難道當時他不小心沒有注意到這個問題,抑或他rp正處低谷,抑或是他一時不負責任無緣無故就愛咋咋地了?!
毛主席教導我們“沒有調查就沒有發言權”;我D強調全社會要樹立科學發展觀。認識到問題的嚴重性,所以樓豬又在本地測試了一下:

ExpandedBlockStart.gif程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CSStudy
{
    
class Program
    {
        
private static int executeTimes = 0;

        
static void Main(string[] args)
        {
            
foreach (string item in CreateStrArr())//這裡呼叫CreateStrArr方法,CreateStrArr會執行多次嗎?
            {
                Console.WriteLine(item);
            }

            Console.WriteLine(
"As you see,method CreateStrArr execute times:{0}", executeTimes);

            Console.ReadKey();
        }

        
static List<string> CreateStrArr()
        {
            executeTimes
++;//記錄CreateStrArr方法到底跑了幾遍
            List<string> listResults = new List<string>();
            
for (int i = 0; i < 5; i++)
            {
                listResults.Add((i 
+ 1).ToString());
            }
            
return listResults;
        }
    }

}

   測試結果印證了這個世界“不會有無緣無故的恨,當然也不會有無緣無故的愛”。正如測試結果顯示的那樣,CreateStrArr方法只跑了一遍,靜態方法CreateStrArr改成例項方法,效果一樣(原諒NC樓豬心裡陰暗,本來是鐵了心要看笑話的...),應該不會有效率問題,那個寫程式碼的人可以笑了。
  失落的樓豬又查了一遍msdn,“foreach 語句為陣列或物件集合中的每個元素重複一個嵌入語句組。foreach 語句用於迴圈訪問集合以獲取所需資訊,但不應用於更改集合內容以避免產生不可預知的副作用.”,明顯沒有告訴我們為什麼示例中的foreach裡的方法只執行一次。又google了一下之後,終於發現原來是編譯時,編譯器對foreach做了優化。nnd,老以為rp出問題,原來是編譯器的魔法,服了。

附:找出表中某個欄位的重複值

在之前的iBATIS.net文章裡我們提到一個person表:

ExpandedBlockStart.gif程式碼
CREATE TABLE [dbo].[Person](
    
[PER_ID] [int] IDENTITY(1,1NOT NULL,
    
[PER_FIRST_NAME] [nvarchar](40) COLLATE Chinese_PRC_CI_AS NOT NULL,
    
[PER_Last_NAME] [nvarchar](40) COLLATE Chinese_PRC_CI_AS NOT NULL,
    
[PER_BIRTH_DATE] [datetime] NULL,
    
[PER_WEIGHT_KG] [float] NULL,
    
[PER_HEIGHT_M] [float] NULL,
 
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
(
    
[PER_ID] ASC
)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ONON [PRIMARY]
ON [PRIMARY]

 在測試的時候,已經被迴圈匯入了很多重複資料,然後,筆者準備檢視一下哪些名字(PER_FIRST_NAME)的記錄是重複的。一開始也不知道是哪根筋出了問題,NC樓豬發揚一不怕苦,二不閒累的精神,先嚐試用自連線的方式來查詢。倒騰若干時間未果後,又秉承一貫堅持不懈認真負責的態度,接著改用臨時表查詢,繼續未果後......我kao,還沒到放假過年呢,怎麼那麼喜慶?在重新確定自己要幹什麼的時候,欣然發現下面這一句就可以了:

     select PER_FIRST_NAME,count(PER_FIRST_NAME) AS TmpCount
     
from person
     
group by PER_FIRST_NAME
     
having count(PER_FIRST_NAME)>1

 太陽啊,這不就是利用SQL的count和分組功能麼,怎麼一開始會想那麼複雜高深呢?要尋找智商上的優越感也太明顯了吧?所以,以後我們要找出表中某個欄位的重複值,只要一句簡單的SQL語句即可(原理就是count+分組):
  select 欄位名,count(欄位名) from 表名 group by 欄位名 having count(欄位名)>1

什麼,您已經樂了?這木有任何技術含量?您找到了自信?!樓豬在此向您表示極度的遺憾。人麼,總(允許)有犯傻rz的時候啊。

 

相關文章