Ce type de problème est un excellent exemple de la raison pour laquelle LINQ a été introduit en C# et VB.NET. Dans .NET 3.5 et versions ultérieures, LINQ fournit la "méthode plus propre" que vous recherchez pour résoudre ce problème.
Malheureusement, parce que vous utilisez .NET 2.0, vous aurez résolu le problème de façon plus ou moins "manuelle". Cependant, vous pouvez toujours écrire du code propre en encapsulant la fonctionnalité que vous recherchez dans des classes et des méthodes bien définies. C'est l'un (mais pas le seul) des avantages de LINQ, c'est-à-dire qu'il encapsule les fonctionnalités que vous attendez d'une manière propre et déclarative.
Voici quelques exemples de code pour vous aider à démarrer:
'The AggregateItem and AggregateItems classes will help encapsulate the '
'the functionality you are looking for.'
Public Class AggregateItem
Public Property GroupByProperty1 As Integer ' Get/Set code...'
Public Property GroupByProperty2 As Integer ' Get/Set code...'
Public Property Values As List(Of Double) = New List(Of Double()() _
' Get/Set code...'
Public Function GetAverage() As Double
'Code to calculate and return Average...'
End Function
End Class
Public Class AggregateItems
Public Property AggregateItemList As List(Of AggregateItem) = _
New List(Of AggregateItem)() ' Get/Set code...'
Public Sub InsertAggregateItem(groupByProperty1 As Integer, _
groupByProperty2 As Integer, _
value As Double)
Dim aiExisting As AggregateItem
aiExisting = GetMatchingAggregateItem(groupByProperty1, _
groupByProperty2)
If Not aiExisting Is Nothing Then
aiExisting.Values.Add(value)
Else
aiExisting = New AggregateItem
aiExisting.GroupByProperty1 = groupByProperty1
aiExisting.GroupByProperty2 = groupByProperty2
aiExisting.Values.Add(value)
AggregateItemList.Add(aiExisting)
End Sub
Private Function GetMatchingAggregateItem(groupByProperty1 As Integer, _
groupByProperty2 As Integer) _
As AggregateItem
Dim aiMatch As AggregateItem = Nothing
For Each ag As AggregateItem in AggregateItemList
If ag.GroupByProperty1 = groupByProperty1 AndAlso _
ag.GroupByProperty2 = groupByProperty2 Then
aiMatch = ag
Exit For
End If
Next
Return aiMatch
End Function
Enc Class
'Then, to consume these classes....'
Public Module MyProgram
Public Sub Main()
Dim aItems As New AggregateItems()
'Say you have List(Of Order) named listOfOrders'
'We will loop through that list, insert the grouping IDs and values'
'into our AggregateItems object'
For Each o As Order In listOfOrders
aItems.InsertAggregateItem(o.OrderId, o.ProductId, o.ProductCount)
Next
'Now we can loop through aItems to cleanly get the average: '
For Each ai As AggregateItem in aItems.AggregateItemsList
Console.WriteLine("Order: {0} Product: {1} Average: {2}", _
ai.GroupByProperty1, ai.GroupByProperty2, _
ai.GetAverage())
Next
End Sub
End Module
La bonne chose sur l'insertion de vos données dans des classes bien encapsulées est que le code est très succincte consommation et facile à comprendre. En outre, puisque vos données sont déjà agrégées dans une classe AggregateItem
, vous pouvez facilement étendre cette classe avec d'autres méthodes telles que GetSum()
ou GetMax()
. De toute évidence, vous pouvez continuer sur cette voie de l'abstraction pour obtenir une meilleure réutilisation de votre code, mais je pense que cela vous donne un bon début.
Thanx Ben. Je n'ai pas eu besoin d'agréger sur les données, nous allons aborder cela d'une manière différente puisque nous allons mettre à jour notre application à 3.5 de toute façon plus tard .. Votre solution semble être quelque chose à essayer pour d'autres problème similaire que j'avais! :) – Mcad001
@Mcad Bon à savoir que vous êtes en train de mettre à niveau. Je ne pense pas qu'il y ait une chance que vous puissiez convaincre votre équipe de passer à la version 4.0? –