Как реализовать шаблон итератора в VB.NET, который не имеет ключевого слова yield
?
Итератор в VB.NET(С# будет использовать выход!)
Ответ 1
Теперь это поддерживается в VS 2010 SP1 с помощью Async CTP, см. Итераторы (С# и Visual Basic) в MSDN и загрузить Visual Studio Async CTP (версия 3).
Код, такой как этот, работает:
Private Iterator Function SomeNumbers() As IEnumerable
' Use multiple yield statements.
Yield 3
Yield 5
Yield 8
End Function
Ответ 2
Я все еще склоняюсь к этой концепции. Статья Использовать итераторы в VB Now была недавно опубликована в журнале Visual Studio.
Ответ 3
VB.NET не поддерживает создание пользовательских итераторов и, следовательно, не имеет эквивалента ключевому слову С# yield. Тем не менее, вы можете захотеть взглянуть на статью KB Как сделать класс Visual Basic.NET или Visual Basic 2005 пригодным для использования в инструкции для каждого пользователя для получения дополнительной информации.
Ответ 4
Хм, похоже, что вы можете из-за удачи:
Сегодня я боролся с проблемой при конвертации некоторых С# в VB.NET. С# имеет действительно классный оператор return return, который используется в блоке итератора для предоставления значения объекту перечислителя. У VB.NET нет ключевого слова "yield". Итак, есть несколько решений (ни одна из которых не очень чистая), чтобы обойти это. Вы можете использовать оператор return, чтобы вернуть значение, если вы зацикливаетесь и хотите разбить перечислитель и вернуть одно значение. Однако, если вы хотите вернуть все перечисление, создайте List() дочернего типа и верните список. Поскольку вы обычно используете это с IEnumerable, List() будет работать хорошо.
Это было написано год назад, не уверен, что с тех пор кто-то придумал что-нибудь еще.
Изменить: это будет возможно в версии 11 VB.NET(после VS2010), планируется поддержка итераторов. Спецификация доступна здесь.
Ответ 5
Ключевое словоС# yield заставляет компилятор создать конечный автомат в фоновом режиме для его поддержки. У VB.Net нет ключевого слова yield. Но у него есть конструкция, которая позволит вам создать конечный автомат внутри функции: Элементы статической функции.
Должно быть возможно воспроизвести эффекты функции возврата доходности, создав общий класс, который реализует IEnumerable, а также необходимый конечный автомат и помещает экземпляр как статический член внутри вашей функции.
Это, конечно, потребует реализации класса вне функции. Но если все сделано правильно, класс должен быть повторно использован в общем случае. Я не играл с идеей, достаточной для предоставления каких-либо деталей реализации.
Ответ 6
Имейте в виду, что отложенное выполнение и ленивые оценочные свойства выражений и методов LINQ позволяют нам эффективно реализовывать пользовательские итераторы до тех пор, пока в .NET 4.5 не появится оператор yield. Доходность используется внутренне выражениями и методами LINQ.
Следующий код демонстрирует это.
Private Sub AddOrRemoveUsersFromRoles(procName As String,
applicationId As Integer,
userNames As String(),
rolenames As String())
Dim sqldb As SqlDatabase = CType(db, SqlDatabase)
Dim command As DbCommand = sqldb.GetStoredProcCommand(procName)
Dim record As New SqlDataRecord({New SqlMetaData("value", SqlDbType.VarChar,200)})
Dim setRecord As Func(Of String, SqlDataRecord) =
Function(value As String)
record.SetString(0, value)
Return record
End Function
Dim userNameRecords As IEnumerable(Of SqlDataRecord) = userNames.Select(setRecord)
Dim roleNameRecords As IEnumerable(Of SqlDataRecord) = rolenames.Select(setRecord)
With sqldb
.AddInParameter(command, "userNames", SqlDbType.Structured, userNameRecords)
.AddInParameter(command, "roleNames", SqlDbType.Structured, roleNameRecords)
.AddInParameter(command, "applicationId", DbType.Int32, applicationId)
.AddInParameter(command, "currentUserName", DbType.String, GetUpdatingUserName)
.ExecuteNonQuery(command)
End With
End Sub
Ответ 7
Ниже приведены результаты: 2, 4, 8, 16, 32
В VB.NET
Public Shared Function setofNumbers() As Integer()
Dim counter As Integer = 0
Dim results As New List(Of Integer)
Dim result As Integer = 1
While counter < 5
result = result * 2
results.Add(result)
counter += 1
End While
Return results.ToArray()
End Function
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
For Each i As Integer In setofNumbers()
MessageBox.Show(i)
Next
End Sub
В С#
private void Form1_Load(object sender, EventArgs e)
{
foreach (int i in setofNumbers())
{
MessageBox.Show(i.ToString());
}
}
public static IEnumerable<int> setofNumbers()
{
int counter=0;
//List<int> results = new List<int>();
int result=1;
while (counter < 5)
{
result = result * 2;
counter += 1;
yield return result;
}
}