VB.NET — Передающее выражение, которое будет использоваться в функции

#vb.net #lambda #parameters #delegates

Вопрос:

Часть моей программы состоит из серии шагов, которые либо завершаются, либо истекают через определенный промежуток времени. Условия испытаний сильно различаются. Как мне написать одну функцию, чтобы инкапсулировать все возможности?

Для этого мне в идеале нужно было бы передать необходимое условие функции, которая должна быть оценена внутри функции, а не оцениваться как параметр, а затем передаваться функции.

Это то, что я бы в идеале хотел (значительно упрощено):

 Private Function TestCondition(lt;CONDITIONgt;) as Boolean   ' Returns True if lt;CONDITIONgt; fulfilled within 10 seconds  Dim sw as New Diagnostics.StopWatch  sw.Start()  While sw.ElapsedMilliseconds lt; 10000  If lt;CONDITIONgt; Return True  System.Threading.Thread.Sleep(500)  End While  sw.Stop()  Return False End Function  

Функция должна работать с любым выражением, возвращающим логическое значение:

 TestCondition(x=5) TestCondition(System.IO.File.Exists("myfile")  

Очевидно, что вышесказанное не работает, так как в функцию передаются результаты заданных условий, а не сами условия.

Основываясь на других данных, я, вероятно, смогу сделать это,:

  • Реструктуризация моего кода
  • Использование делегатов
  • Использование лямбда-выражений

но я все еще не вижу, как именно.

Большое спасибо за вашу помощь!

Ответ №1:

Вы можете передать лямбду в функцию, которую можно постоянно пересматривать.

 Private Function TestCondition(predicate As Func(Of Boolean)) As Boolean  Dim sw As New Diagnostics.Stopwatch()  sw.Start()  While sw.ElapsedMilliseconds lt; 10000  If predicate() Then Return True  System.Threading.Thread.Sleep(500)  End While  sw.Stop()  Return False End Function  
 Dim result = TestCondition(Function() File.Exists("myfile"))  

Комментарии:

1. Спасибо, это именно то, что я искал!!! Поиск лямбда — функций и ключевого слова «Func» привел меня в настоящую кроличью нору. Я многому научился. Еще раз спасибо!!

Ответ №2:

В основном то же самое, что сказал djv,

 ''' lt;summarygt; ''' waits for a condition for a number of seconds ''' lt;/summarygt; ''' lt;param name="PredicateFunc"gt;Function() conditional check )lt;/paramgt; ''' lt;param name="WaitForTMInSecs"gt;seconds to waitlt;/paramgt; ''' lt;returnsgt;booleanlt;/returnsgt; ''' lt;remarksgt;lt;/remarksgt; Private Function TestCondition(PredicateFunc As Func(Of Boolean),  Optional WaitForTMInSecs As Integer = 10) As Boolean  Dim sw As Diagnostics.Stopwatch = Diagnostics.Stopwatch.StartNew  Dim _wait As TimeSpan = TimeSpan.FromSeconds(WaitForTMInSecs)  Dim rv As Boolean = PredicateFunc()  Do While Not rv AndAlso sw.Elapsed lt;= _wait  System.Threading.Thread.Sleep(500)  rv = PredicateFunc()  Loop  Return rv End Function  

Тесты,

 Dim result As Boolean  result = TestCondition(Function() String.Equals("foo", "bar"), 2)  result = TestCondition(Function() String.Equals("foo", "foo"), 2)  result = TestCondition(Function() IO.File.Exists("myfile"), 2)  

Комментарии:

1. Элегантно — спасибо!