Доходность в VB.NET - PullRequest
       100

Доходность в VB.NET

62 голосов
/ 19 сентября 2008

C # имеет ключевое слово yield . VB.NET не хватает этого ключевого слова. Как программисты Visual Basic обошлись без этого ключевого слова? Они реализуют свой собственный класс итераторов? Или они пытаются и код, чтобы избежать необходимости итератора?

Ключевое слово yield вынуждает компилятор выполнять некоторое скрытое кодирование. Реализация итераторов в C # и ее последствия (часть 1) имеет хороший пример этого.

Ответы [ 8 ]

71 голосов
/ 20 декабря 2008

Примечание. Этот ответ устарел. С тех пор блоки итераторов добавлены в VB.NET

C # переводит ключевое слово yield в конечный автомат во время компиляции. VB.NET не имеет ключевого слова yield, но у него есть собственный механизм для безопасного встраивания состояния в функцию, которая нелегко доступна в C #.

Ключевое слово C # static обычно переводится в Visual Basic с использованием ключевого слова Shared, но есть два момента, где все становится запутанным. Во-первых, статический класс C # на самом деле является модулем в Visual Basic, а не классом Shared (можно подумать, что они позволят вам кодировать его в любом случае в Visual Basic, но это не так). Другое дело, что у VB.NET есть собственное ключевое слово Static. Однако Static имеет другое значение в VB.NET.

Вы используете ключевое слово Static в VB.NET для объявления переменной внутри функции, и при этом переменная сохраняет свое состояние при вызове функции. Это отличается от простого объявления частного статического члена класса в C #, поскольку член статической функции в VB.NET гарантированно также является поточно-ориентированным, поскольку компилятор преобразует его для использования класса Monitor во время компиляции.

Так зачем писать все это здесь? Что ж, должна быть возможность создать универсальный класс Iterator<T> многократного использования (или Iterator(Of T) в VB.NET). В этом классе вы реализуете конечный автомат, используемый C #, с методами Yield() и Break(), которые соответствуют ключевым словам C #. Затем вы могли бы использовать статический экземпляр (в смысле VB.NET) в функции, чтобы в конечном итоге он мог выполнять почти ту же работу, что и yield в C #, примерно в том же объеме кода (отбрасывая саму реализацию класса, поскольку будет бесконечно многократно использоваться).

Я недостаточно заботился о доходности, чтобы попытаться сам, но это должно быть выполнимым. Тем не менее, это также далеко не тривиально, так как член команды C # Эрик Липперт называет это « самым сложным преобразованием в компиляторе ».

Я также пришел к выводу, что с тех пор, как я написал первый черновой вариант этого более года назад, до тех пор, пока не выйдет Visual Studio 2010, это не представляется возможным, так как это потребовало бы отправки нескольких лямбд в класс Iterator и т. чтобы быть действительно практичными, нам нужна поддержка .NET 4 для многострочных лямбд.

21 голосов
/ 05 мая 2011

Async CTP включает поддержку Yield в VB.NET.

См. Итераторы в Visual Basic для получения информации об использовании.

А теперь он включен в комплект поставки Visual Studio 2012!

14 голосов
/ 26 сентября 2009

Есть хорошая статья Использование итераторов в VB Now от Билла Маккарти в журнале Visual Studio об эмуляции yield в VB.NET. В качестве альтернативы дождитесь следующей версии Visual Basic.

3 голосов
/ 11 февраля 2018

К счастью, теперь у нас есть Yield возврат
Вот пример из моего проекта + реализация интерфейса с функцией 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
1 голос
/ 19 сентября 2008

Лично я просто пишу свой собственный класс итераторов, который наследуется от IEnumerator (Of T). Требуется некоторое время, чтобы понять это правильно, но я думаю, что в конце лучше написать это правильно, а затем попытаться избежать этого. Другой метод, который я сделал, это написание рекурсивного метода, который возвращает IEnumerable (Of T) и просто возвращает List (Of T) и использует .AddRange.

0 голосов
/ 22 июня 2017

VB.NET имеет ключевое слово Iterator https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/modifiers/iterator

Начиная с Visual Studio 2012, похоже

0 голосов

Приведенный ниже код дает вывод

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

In C #

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;
    }
}
0 голосов
/ 20 декабря 2008

Надеюсь, это будет делом прошлого с будущей версией VB. Поскольку итераторы на самом деле приобретают большое значение с новыми парадигмами (особенно LINQ в сочетании с ленивой оценкой), это, насколько я знаю из блога Пола Вика, имеет довольно высокий приоритет. С другой стороны, Пол больше не является главой команды VB, и у меня еще не было времени, чтобы посмотреть выступления PCD.

Тем не менее, если вам интересно, они связаны в блоге Пола .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...