(NET) NET(2007 год)

Делегаты сравнения для сортировки и Linq-отборов в VB.NET

В последней версии VB появились ряд новых функций, а для VB примеров явно мало.К счастью, мне недавно попался проект, в котором мне встретилось огромное количество последних нововведений NET 3.5. И я решил немного просуммировать их на этой страничке.

Итак для начала предикат сравления для сортировок коллекций. Мне надо просортировать LINQ-коллекцию

Dim Z3 As System.Collections.Generic.List(Of GetLocalPriceResult)

Тут два варианта - указать непосредственно адрес функции сравнения (разместив ее внутри класса) либо указав название класса, содержащего реализацию интерфейса IComparer:

Тело функции сравнения элементов коллекции в обоих случаях одинаково и выглядит вот так:


   1:  Public Class LocalPrice_Comparer
   2:      Implements IComparer(Of GetLocalPriceResult)
   3:   
   4:      Public Function Compare(x As GetLocalPriceResult, y As GetLocalPriceResult) As Integer Implements System.Collections.Generic.IComparer(Of GetLocalPriceResult).Compare
   5:          If IsNumeric(x.Summ.Replace(",", "")) And IsNumeric(y.Summ.Replace(",", "")) Then
   6:              'сравнение чисел
   7:              If CDec(x.Summ.Replace(",", "")) = CDec(y.Summ.Replace(",", "")) Then
   8:                  Return 0
   9:              ElseIf CDec(x.Summ.Replace(",", "")) > CDec(y.Summ.Replace(",", "")) Then
  10:                  Return 1
  11:              ElseIf CDec(x.Summ.Replace(",", "")) < CDec(y.Summ.Replace(",", "")) Then
  12:                  Return -1
  13:              End If
  14:          ElseIf Not IsNumeric(x.Summ.Replace(",", "")) And Not IsNumeric(y.Summ.Replace(",", "")) Then
  15:              'сравнение строк
  16:              If x.ToString = y.ToString Then
  17:                  Return 0
  18:              ElseIf x.ToString > y.ToString Then
  19:                  Return 1
  20:              ElseIf x.ToString < y.ToString Then
  21:                  Return -1
  22:              End If
  23:          ElseIf IsNumeric(x.Summ.Replace(",", "")) And Not IsNumeric(y.Summ.Replace(",", "")) Then
  24:              'первое число
  25:              Return 1
  26:          ElseIf Not IsNumeric(x.Summ.Replace(",", "")) And IsNumeric(y.Summ.Replace(",", "")) Then
  27:              'второе число
  28:              Return -1
  29:          End If
  30:      End Function

Намного веселее получается, если надо просортировать типозированный массив.

Dim Y As ru.emex.EmExService.DetailItem()

В это варианте существует аж 17 вариантов указать функцию сравнения элементов массива. Пятый и шестой вариант - точно такие же как в предыщем случае сравнения коллекций.

Собственно функция сравнения в моем случае выглядела так (только в одном случае указывается класс, содержащий нужную функцию - а в другом AddressOF этой функции (а сама функция размещается в теле текущего класса:


   1:  Public Class EmExService_DetailItem_Comparer
   2:      Implements IComparer(Of ru.emex.EmExService.DetailItem)
   3:   
   4:      Public Function Compare(x As ru.emex.EmExService.DetailItem, y As ru.emex.EmExService.DetailItem) As Integer Implements System.Collections.Generic.IComparer(Of ru.emex.EmExService.DetailItem).Compare
   5:          If x.Prices.ResultPrice = y.Prices.ResultPrice Then
   6:              Return 0
   7:          ElseIf x.Prices.ResultPrice > y.Prices.ResultPrice Then
   8:              Return 1
   9:          ElseIf x.Prices.ResultPrice < y.Prices.ResultPrice Then
  10:              Return -1
  11:          End If
  12:      End Function
  13:  End Class

Теперь рассмотрим функцию сравнения в Linq-отборе в WHERE. Вообще условия WHERE можно составить и динамически (чаще всего требуется именно это) - но здесь я покажу самый простой вариант.

Итак, в некотороем месте сайта у меня сделан отбор:

            SavedLocalZakaz = (From X In db1.EmexBasket1s Select X Where X.Archive = Archive And X.EmexNum > 0 And X.EmexComment Like AdmSearchPanel_comment And X.EmexStatus = CInt(AdmSearchPanel_status) Order By X.i Descending).ToList
            Return FilterForNum(SavedLocalZakaz)

И из Session мне пришел параметр, по которому надо отфильтровать эту Linq-коллекцию. Этот Session приходит не всегда, конкретно форма фильтра выглядит вот так:

и комбинаций отборов может бють много - поэтому простая статическая запись в Where тут не подойдет. К тому же условие комбинирования условий поиска сформулировано хитро - например DropdownList фильтрует независимо от текстовых полей. Поэтому сначала надо выполнить разбор что именно задано в условиях фильтрации, а потом в некоторых случаях выполнить фильтрацию:


 237:          If ...
 238:          ElseIf AdmSearchPanel_id = "" And AdmSearchPanel_num <> "" And AdmSearchPanel_comment <> "" And AdmSearchPanel_status <> "0" Then
 239:              'AdmSearchPanel_num &  AdmSearchPanel_comment & AdmSearchPanel_Status
 240:              SavedLocalZakaz = (From X In db1.EmexBasket1s Select X Where X.Archive = Archive And X.EmexNum > 0 And X.EmexComment Like AdmSearchPanel_comment And X.EmexStatus = CInt(AdmSearchPanel_status) Order By X.i Descending).ToList
 241:              Return FilterForNum(SavedLocalZakaz)
 242:          ...
 243:          End If

Соответственно где-то в недрах кода этой формы существует вот такой код FilterForNum:


 254:      Shared Function FilterForNum(SavedLocalZakaz As System.Collections.Generic.List(Of Global.Omsk.EmexBasket1)) As System.Collections.Generic.List(Of Global.Omsk.EmexBasket1)
 255:          Dim Z1 = SavedLocalZakaz.Where(AddressOf FilterNum)
 256:          If Z1 Is Nothing Then
 257:              Return Nothing
 258:          Else
 259:              Dim Y1 As New System.Collections.Generic.List(Of Global.Omsk.EmexBasket1)
 260:              For Each One In Z1
 261:                  Y1.Add(One)
 262:              Next
 263:              Return Y1
 264:          End If
 265:      End Function
 266:   

Который соббственно и содержит вызов предиката WHERE запроса LINQ:


 276:      Public Shared Function FilterNum(One As Global.Omsk.EmexBasket1) As Boolean
 277:          Return (One.EmexNum.ToString.Contains(HttpContext.Current.Session("AdmSearchPanel_num")))
 278:      End Function

Продолжение о реализации новых возможностей NET 3.5 на VB.NET вы можете почитать в топике - Практическое применение наследования, полиморфизма, интерфейсов, дженериков и делегатов на примерах в Visual Basic .NET

Comments ( )
Link to this page: //www.vb-net.com/CompareCollections/index.htm
< THANKS ME>