#arrays #vb.net #function #collections
#массивы #vb.net #функция #Коллекции
Вопрос:
Я пишу действительно базовую функцию, которая сортирует входящие электронные письма в групповой почтовый ящик по папкам в зависимости от того, кому они предназначены для чтения. Это глупая вещь, которую нужно делать, поскольку у всех нас есть свои адреса электронной почты, но компании часто делают глупые вещи!
Критерии, которые определяют, «кому предназначено электронное письмо», довольно сложны, поэтому я пишу серию простых функций, которые будут возвращать, если это «для» конкретного человека
Function IsRichard(msg As Outlook.MailItem) As Boolean
...
End Function
Function IsTim(msg As Outlook.MailItem) As Boolean
...
End Function
В настоящее время я запускаю все это последовательно в функции управления Function WhoIsItFor()
. Однако этот подраздел теперь становится немного длинным и неуклюжим, поэтому мне было интересно, можно ли определить массив или коллекцию функций, чтобы я мог сделать что-то вроде:
Const AllFunctions as Function () = {IsRichard, IsTim ...}
Function WhoIsItFor(msg as Outlook.MailItem) as String
For Each thisFunction as Function in AllFunctions
if thisFunction(msg) then
return (thisFunction.name)
end if
next
end function
Ответ №1:
Вы должны использовать оператор AddressOf и определить тип массива с помощью функции делегирования:
Dim AllFunctions() As Func(Of Outlook.MailItem, Boolean) = {AddressOf IsRichard, AddressOf IsTim}
Function WhoIsItFor(msg As Outlook.MailItem) As String
For Each thisFunction As Func(Of Outlook.MailItem, Boolean) In AllFunctions
If thisFunction(msg) Then
Return thisFunction.Method.Name
End If
Next
Return Nothing
End Function
Комментарии:
1. Это очень близко к правильному, но вы сначала протестировали это? Он не компилируется.
2. Вы также могли бы избежать
For
цикла с помощью этого:AllFunctions.Where(Function (f) f(msg)).Select(Function (f) f.Method.Name).FirstOrDefault()
.3. Я только что скомпилировал его, имитируя Outlook. MailItem и сработал. Какую ошибку вы получили?
4. Извините, это предупреждение компилятора — c # приведет к ошибке, но VB кажется намного более мягким, ad допускает неправильный код. Предупреждение заключается в том, что не все пути кода возвращают значение. Что произойдет, если ни одна из функций не вернет
True
?5. Результат будет ничем не отличаться от вашего предложения заменить цикл For выражением linq.
Ответ №2:
Альтернативный подход заключается в создании класса (vb.net это объектно-ориентированный язык ;)) для представления человека (или чего-либо, что может «реагировать» на электронное письмо).
При таком подходе при добавлении или удалении пользователей вам не нужно касаться «основного» кода, который обрабатывает электронные письма.
' Create an abstraction to represent mail handler
Public Interface IMailHandler
Function CanHandle(MailItem mail) As Boolean
Sub Handle(MailItem mail)
End Interface
' Implement for Tim
Public Class Tim Inherits IMailPerson
Public Function CanHandle(MailItem mail) As Boolean
Return mail.Subject = "For Tim"
End Function
Public Sub Handle(MailItem mail)
' Move to Tim folder
End Sub
End Class
' Implement for Bob
Public Class Bob Inherits IMailPerson
Public Function CanHandle(MailItem mail) As Boolean
' Can be anything else
End Function
Public Sub Handle(MailItem mail)
' Delete Bob messages
End Sub
End Class
Использование
Dim handlers As New List(Of IMailHandler) From { New Tim(), New Bob() }
var handler = handlers.
Where(Function (h) h.CanHandle(mail)).
DefaultIfEmpty(new DefaultHandler()).
First()
handler.Handle(mail)
С помощью описанного выше подхода вы можете сохранить связанную логику в одном месте:
- решение о том, «можно ли обработать это письмо»
- фактическое действие для этого письма