2015-12-03 52 views
1

我有一個DataGridView,實際上可能有多達2000行和100列。我想循環遍歷所有單元格,並根據單元格中基礎數據的性質將內容添加到列表中。該代碼目前看起來是這樣的:最快的單元格迭代方法

for (var columnIndex = 1; columnIndex < edgv.ColumnCount; columnIndex++) 
{ 
    for (var rowIndex = 1; rowIndex < edgv.RowCount; rowIndex++) 
    { 
     var currentValue = edgv[columnIndex, rowIndex].Value as ISomeInterface; 
     if (currentValue != null && (currentValue.GetType().Equals(typeof(SomeClass).FullName)) 
      && (((SomeClass)currentValue).Attribute != null)) 
     { 
      values.Add(currentValue); 
     } 
    } 
} 

此代碼適用於較小的電網,但似乎陷入癱瘓(如果不是搪塞了完全)時,列數和行數開始越來越大。我想知道是否將for循環更改爲foreach循環可能會有所幫助,並且我願意接受其他想法。

有什麼想法?

+1

一個foreach仍然是一個循環。不要猜測瓶頸,嘗試測試它。如果您註釋掉當前的代碼,它運行得有多快? – LarsTech

+2

我想你應該旋轉一個原型並自己測試一下。這是很好的編程業力。 – Will

+1

這似乎很奇怪'currentValue.GetType()。Equals(typeof(SomeClass).FullName)''。爲什麼不只是'currentValue。GetType()== typeof(SomeClass)''''''''或'currentValue是SomeClass',或者更好地使用'作爲SomeClass'來代替,你只需要'if(currentValue!= null && currentValue.Attribute!= null)' – juharr

回答

0

提高現有流程性能的第一步通常應該是分析。分析器會告訴你哪一段代碼需要最多的時間,讓你知道哪些部分需要優化。很多時候,瓶頸是你最不期待的地方,如果沒有探查器,你可能會浪費大量時間來優化代碼,這將使你的實際性能提高接近零。

而現在,我會忽略我在上一段已經說給大家幾點建議:

  1. 你不同意,你創建values集合的代碼。假設它是一個List,它有一個構造函數來獲取容量參數。這對於性能可能非常重要。如果使用空的構造函數,則默認容量爲5,如果向集合中插入大量值,這可能會對性能造成災難性影響。 其原因在於該列表內部實現爲「容量」長度的數組,並且每當您在長度上插入一個項目時,它將創建一個長度爲兩倍的新數組(現在將成爲新容量),並將舊數組中的所有項目複製到新數組中。 複製過程會損害性能。還必須始終分配新陣列(並刪除舊陣列)將導致GC運行amoc,並且還可能導致內存碎片化,所有這些都可能成爲代碼中的潛在瓶頸。 所以你應該在創建你的列表時選擇適當的容量。您應該根據您對最常見情況下將列入清單的項目數量來選擇容量。 如果,例如,您希望通常插入幾乎所有的細胞,你可以撥打:values = new List<SomeClass>(edgv.ColumnCount * edgv.RowCount);

  2. 它在評論中已經說了,但在每個單元迭代你投以ISomeInterface,然後轉換爲SomeClass。因爲你真的沒有使用ISomeInterface這是多餘的。只需鑄造到SomeClass就足夠了,可能會提升性能。

    for (var columnIndex = 1; columnIndex < edgv.ColumnCount; columnIndex++) 
        { 
         for (var rowIndex = 1; rowIndex < edgv.RowCount; rowIndex++) 
         { 
          var currentValue = edgv[columnIndex, rowIndex].Value as SomeClass; 
          if (currentValue != null && currentValue.Attribute != null) 
          { 
           values.Add(currentValue); 
          } 
         } 
        } 
    
  3. 也有人說,在評論中,你可能並不需要遍歷所有單元格。通常在網格中,每列的類型是相同的。如果你的情況也是如此,那麼你可以檢查每一列中的第一個單元格,並根據它的類型,可以避免檢查該列中的其他單元格。

    for (var columnIndex = 1; columnIndex < edgv.ColumnCount; columnIndex++) 
        { 
         for (var rowIndex = 1; rowIndex < edgv.RowCount; rowIndex++) 
         { 
          var currentValue = edgv[columnIndex, rowIndex].Value as SomeClass; 
          if (currentValue == null) break; //Skipping the check for this column 
          if (currentValue.Attribute != null) 
          { 
           values.Add(currentValue); 
          } 
         } 
        } 
    
+0

'values'是一個'List ',因此是最初的演員。大部分發生的事情基本上是防彈的,儘管我發現自己認爲擴大默認容量(如您所建議的)可能會有所幫助。 –

+0

是的,但'SomeClass'繼承自'ISomeInterface',你只關心'SomeClass',所以最初的轉換依然是多餘的。不需要bulletproffing,因爲如果'SomeClass'沒有從'ISomeInterface'繼承,它就不會編譯。 – tzachs