Выход в VB.NET
С# имеет ключевое слово yield. VB.NET не хватает этого ключевого слова. Как программисты на Visual Basic воспользовались отсутствием этого ключевого слова? Они реализуют свой класс итераторов? Или они пытаются и кодируют, чтобы избежать необходимости итератора?
yield ключевое слово заставляет компилятор делать некоторую кодировку за кулисами. Хорошим примером этого является реализация итераторов в С# и его последствиях (часть 1).
Ответы
Ответ 1
Примечание. Этот ответ уже устарел. С тех пор блоки итераторов были добавлены в VB.NET
С# переводит ключевое слово yield в конечный автомат во время компиляции. VB.NET не имеет ключевого слова yield, но у него есть собственный механизм для безопасного встраивания состояния в функцию, которая нелегко доступна в С#.
Ключевое слово С# static
обычно переводится в Visual Basic с помощью ключевого слова Shared
, но есть два момента, где все становится запутанным. Во-первых, статический класс С# на самом деле является модулем в Visual Basic, а не классом Shared (можно подумать, что они позволят вам кодировать его в любом случае в Visual Basic, но это не так). Другое дело, что VB.NET имеет свое собственное ключевое слово Static
. Однако Static
имеет другое значение в VB.NET.
Вы используете ключевое слово Static
в VB.NET, чтобы объявить переменную внутри функции, и когда вы это делаете, переменная сохраняет свое состояние при вызове функции. Это отличается от простого объявления закрытого статического члена класса в С#, поскольку член статической функции в VB.NET гарантированно также является поточно-ориентированным, поскольку компилятор преобразует его для использования класса Monitor во время компиляции.
Так зачем писать все это здесь? Ну, должно быть возможно создать универсальный класс Iterator<T>
многократного использования (или Iterator(Of T)
в VB.NET). В этом классе вы реализуете конечный автомат, используемый С#, с методами Yield()
и Break()
, которые соответствуют ключевым словам С#. Затем вы можете использовать статический экземпляр (в смысле VB.NET) в функции, чтобы в конечном итоге он мог выполнять почти ту же работу, что и С# yield
, примерно в том же объеме кода (отбрасывая саму реализацию класса, поскольку будет бесконечно многократно использоваться).
Я недостаточно заботился о Yield, чтобы попробовать это сам, но это должно быть выполнимо. Тем не менее, это также далеко не тривиально, так как член команды С# Эрик Липперт называет это "самым сложным преобразованием в компиляторе".
Я также пришел к выводу, что с тех пор, как я написал первый черновой вариант этого более года назад, до тех пор, пока не выйдет Visual Studio 2010, это не представляется возможным, поскольку это потребует отправки нескольких лямбда-выражений в класс Iterator и, таким образом, будет действительно на практике нам нужна поддержка .NET 4 для многострочных лямбд.
Ответ 2
Async CTP включает поддержку Yield
в VB.NET.
Для получения информации об использовании см. Итераторы в Visual Basic.
И теперь он включен в коробку с Visual Studio 2012!
Ответ 3
Там хорошая статья Использование итераторов в VB Now Билла МакКарти в журнале Visual Studio Magazine по эмуляции yield
в VB.NET. В качестве альтернативы дождитесь следующей версии Visual Basic.
Ответ 4
К счастью, теперь у нас есть Yield
return
Вот пример из моего проекта + реализация интерфейса с функцией System.Collections.Generic.IEnumerable(T)
:
Public Class Status
Implements IStatus
Private _statusChangeDate As DateTime
Public Property statusChangeDate As DateTime Implements IStatus.statusChangeDate
Get
Return _statusChangeDate
End Get
Set(value As Date)
_statusChangeDate = value
End Set
End Property
Private _statusId As Integer
Public Property statusId As Integer Implements IStatus.statusId
Get
Return _statusId
End Get
Set(value As Integer)
_statusId = value
End Set
End Property
Private _statusName As String
Public Property statusName As String Implements IStatus.statusName
Get
Return _statusName
End Get
Set(value As String)
_statusName = value
End Set
End Property
Public Iterator Function GetEnumerator() As IEnumerable(Of Object) Implements IStatus.GetEnumerator
Yield Convert.ToDateTime(statusChangeDate)
Yield Convert.ToInt32(statusId)
Yield statusName.ToString()
End Function
End Class
Public Interface IStatus
Property statusChangeDate As DateTime
Property statusId As Integer
Property statusName As String
Function GetEnumerator() As System.Collections.Generic.IEnumerable(Of Object)
End Interface
Вот как я извлекаю все свойства снаружи:
For Each itm As SLA.IStatus In outputlist
For Each it As Object In itm.GetEnumerator()
Debug.Write(it & " ")
Next
Debug.WriteLine("")
Next
Ответ 5
Лично я просто пишу свой собственный класс итераторов, который наследуется от IEnumerator(Of T)
. Требуется некоторое время, чтобы понять это правильно, но я думаю, что в конце лучше написать это правильно, а затем попытаться избежать этого. Другой метод, который я сделал, - это написание рекурсивного метода, который возвращает IEnumerable(Of T)
и просто возвращает List(Of T)
и использует .AddRange
.
Ответ 6
Надеюсь, что это будет в прошлом с предстоящей версией VB. Поскольку итераторы на самом деле приобретают большое значение с новыми парадигмами (особенно LINQ в сочетании с ленивой оценкой), это имеет довольно высокий приоритет, насколько мне известно из блога Пола Вика. Опять же, Пол больше не является главой команды VB, и я еще не успел посмотреть переговоры по PCD.
Тем не менее, если вам интересно, они связаны в Paul blog.
Ответ 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;
int result=1;
while (counter < 5)
{
result = result * 2;
counter += 1;
yield return result;
}
}
Ответ 8
VB.NET имеет ключевое слово Iterator
https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/modifiers/iterator
Так как Visual Studio 2012 кажется