Этот тип проблемы является отличным примером того, почему LINQ был введен в C# и VB.NET. В .NET 3.5 и выше LINQ предоставляет «более чистый путь», который вы ищете для решения этой проблемы.
К сожалению, поскольку вы используете .NET 2.0, вы решите проблему более или менее «вручную». Однако вы все равно можете писать чистый код, инкапсулируя функциональность, которую вы ищете, в четко определенные классы и методы. Это одно (но не единственное) преимущество LINQ, то есть оно инкапсулирует функциональность, которую вы ожидаете, в чистой, декларативной манере.
Вот некоторые примеры кода, чтобы вы начали:
'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
Хорошая вещь о вставке данных в хорошо герметизированных классов является то, что потребляя код очень кратким и легко понять. Кроме того, поскольку у вас уже есть данные, объединенные в класс AggregateItem
, вы можете легко расширить этот класс с помощью большего количества методов, таких как GetSum()
или GetMax()
.
Очевидно, что вы можете продолжить этот путь абстракции, чтобы лучше использовать его из своего кода, но я думаю, что это дает вам хорошее начало.
Thanx Ben. Мне не нужно было агрегировать данные, мы подойдем к этому по-другому, так как мы все равно обновим наш appz до 3.5. Ваше решение кажется чем-то другим, чтобы попробовать, если они столкнутся с проблемой аналогичная проблема, которая у меня была! :) – Mcad001
@Mcad Приятно слышать, что вы обновляете. Я не думаю, что есть шанс, что вы сможете убедить свою команду идти вперед и обновиться до 4.0? –