Click here to Skip to main content
15,887,027 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hello everyone, I have another translation problem that not even - chat.openai.com - could help me, I use vb 2010, and I know very well that from the 2012 version "yield" is supported, but for compatibility I have to use the 2010 version. Is there a not too far-fetched alternative to get around the problem? The code is as follows:
C#
public IEnumerable<Range> GetRanges(string regexPattern)
         {
             var range = new Range(this);
             range.SelectAll();
             //
             foreach (Range r in range.GetRanges(regexPattern, RegexOptions.None))
                 yield return r;
         }

I hope for your help and thank you.

What I have tried:

I tried this, but it doesn't work, the program crashes and I restart vb...
VB
Module Module1
     Sub Main()
         For Each number In GenerateNumbers(1, 5)
             Console.WriteLine(number)
         Next
         Console.ReadLine()
     End Sub

     Function GenerateNumbers(start As Integer, count As Integer) As Integer()
         Dim result(count - 1) As Integer
         For i As Integer = 0 To count - 1
             result(i) = start + i
         Next
         Return result
     End Function
End Module
Posted
Updated 5-Feb-24 4:02am
v2
Comments
Richard MacCutchan 5-Feb-24 3:42am    
Do what everyone suggests, and upgrade to a version that supports it.

I wouldn't say that it was "not a simple job", just done differently to C#. Here is how: Iterator - Visual Basic | Microsoft Learn[^]

So, at a guess (not tested), the VB.Net version should be:
VB
Public Iterator Function GetRanges(regexPattern As String) As IEnumerable(Of Range)
    Dim range As New Range(Me)
    range.SelectAll()
    
    For Each r As Range In range.GetRanges(regexPattern, RegexOptions.None)
        Yield r
    Next
End Function
 
Share this answer
 
Comments
10071962 5-Feb-24 2:36am    
Thank you, but "Yield" is not supported by the 2010 version...
Graeme_Grant 5-Feb-24 2:37am    
why use a version that is over 13 years old?
10071962 5-Feb-24 2:48am    
Because up until now it has always been perfect for my uses...
Graeme_Grant 5-Feb-24 3:51am    
Time to take the leap and modernise if you want the modern features...
Dave Kreskowiak 5-Feb-24 11:26am    
You are the only person holding you back. There is no difference between 2010 and later versions that you cannot use or adapt to.

Your question alone is reason enough to upgrade.
There was a period where yield was available in C# but not in vb. If that was the case in 2010 then check whether the IEnumerable interface was available in vb in 2010?

If the IEnumerable interface was available in vb in 2010 then you can implement that interface for a class you create in order to create a Yield like functionality. See this article[^], it's not actually that hard.

If the IEnumerable interface wasn't available in vb in 2010 then either see OriginalGriff's answer or implement the code below but remove all of the interface implementations. Not implementing the intefaces means that you won't be able to use For ... Each but the While .MoveNext() = True code should still work - examples are included below.

For example (I haven't tested this code so there will be typos that should be easy to fix).
First you create a new class that can be enumerated (implements IEnumerable). The article I linked above describes all of this in detail but in essence the new class implements IEnumerable which means it must have the ability to create and return an object that implements IEnumerator.
VB
Public Class VBYield
    Implements IEnumerable(Of Integer)
    
    Private _enumerableobject As Integer()
    Private _thingenumerator As ThingEnumerator
    
    Public Sub New(EnumerableObject As Integer())
        Me._enumerableobject = EnumerableObject
    End Sub
    
    Public Function GetEnumerator() As IEnumerator(Of Double) Implements IEnumerable(Of Integer).GetEnumerator
        Return New ThingEnumerator(Me._enumerableobject)
    End Function
    
    ''' <summary>
    ''' [Use GetEnumerator instead]
    ''' </summary>
    Public Function GetEnumerator1() As IEnumerator Implements Collections.IEnumerable.GetEnumerator
        Return Me.GetEnumerator()
    End Function

Then we create the enumerator that will be used by the enumerable object. You can see that the array of integers is progressively passed from your code to the IEnumerable object and then the IEnumerator object. You need to decide if it should be shallow (by reference) or deep (by value) copies based on your needs.
VB
Public Class ThingEnumerator
    Implements IEnumerator(Of Integer)
 
    Private _enumerableobject As Integer()
    Private _index As Integer
    Private _curItem As Integer
    Private _lastItem As Integer
 
    Public Sub New(enumerableobject As Integer())
        Me._enumerableobject = enumerableobject
        Me._index = -1
        Me._curItem = Nothing
        Me._lastItem = enumerableobject.GetUpperBound(0)
    End Sub

Then modify your original code to use this new class. Note that there are two ways to do the enumeration
VB
Sub Main()
    'Create the object that can be enumerated
    Dim enumerablething As VBYield = New VBYield(GenerateNumbers(1,5))
    
    'There are two ways to enumerate the contents of our new object
    'This first way makes use of the fact that the object is enumerable (cannot use For Each if it isn't)
    For Each number As Interger in VBYield
        Console.WriteLine(number.ToString())
    Next
    
    'This second way ignorers the fact that the object is enumerable and accesses the methods of the enumerator object directlty
    'Use the enumerable object to get an enumerator object and then use MoveNext() and Current() to traverse its contents
    Dim enumeratorofthing As IEnumerator = VBYield.GetEnumerator()
    While enumeratorofthing.MoveNext() = True
        Console.WriteLine(enumeratorofthing.Current.ToString())
    End While

End Sub

Function GenerateNumbers(start As Integer, count As Integer) As Integer()
    Dim result(count - 1) As Integer
    For i As Integer = 0 To count - 1
        result(i) = start + i
    Next
    Return result
End Function

Then you need to implement the IEnumerator interface for the ThingEnumerator class.
VB.NET
Public ReadOnly Property Current As Double Implements IEnumerator(Of Integer).Current
    Get
        If IsNothing(Me._curItem) Then
            Throw New InvalidOperationException()
        End If
        Return Me._curItem
    End Get
End Property

Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
    If Me._index = Me._lastItem Then
        Return False
    End If
    Me._index += 1
    Me._curItem = Me._enumerableobject(Me._index)
    Return True
End Function

Public Sub Reset() Implements IEnumerator.Reset
    Me._index = -1
    Me._curItem = Nothing
End Sub
 
Share this answer
 
Comments
10071962 5-Feb-24 5:54am    
Monstrous work, congratulations. I was wondering if it could work the same if instead of passing integer values I pass strings or dots... Also how do you know the value of "enumerableobject" in advance? going back to my example:

public IEnumerable<range> GetRanges(string regexPattern)
{
var range = new Range(this);
range.SelectAll();
//
foreach (Range r in range.GetRanges(regexPattern, RegexOptions.None))
yield return r;
}

How would you pass it on to your class?

Thank you!
M-Badger 5-Feb-24 9:28am    
I am not sure what "instead of passing integer values I pass strings or dots" means, especially "dots".

The IEnumerable and IEnumerator are specific to the enumerable object in the IEnumerable class that you create so you can have an array of strings or any other type of object; you can have Lists, Colections etc. In your case you had a 1-dimensional array of integers so the code was written to that, if it was a 2-dimensional array or an array of double then the code would need to be adapted. I don't know if it possible to write equivalent late binding code to make it generic and I'm not going to try.

My answer showed you how to modify your "What have I tried?" code.

It may be my lack of ability but your C# does not make a lot of sense to me. For example you create a Range object and then instantiate it with a reference to 'this', so 'this' must be a Range object (a tuple of Index) and then you call the GetRanges method of that Range object but the Range class doesn't have a GetRanges method (nor for that matter does it have a SelectAll method). I wonder if 'this' is actually a string?

So assuming what you want is an array of range objects that indicate the start and end indexes of all occurrences of the search string within a larger string then, as the saying goes, I wouldn't start by trying to convert that C# code to a VB equivalent. Personally (not a professional) I'd create a List or a Collection of Range objects (if Collections/Lists were available in 2010) based on code that does the pattern matching and which populates the List/Collection. You then have an object which is enumerable. Or you can create an array of Range objects and implement IEnumerable/IEnumerator as shown.
10071962 5-Feb-24 10:00am    
Thank you, I'll do some tests and see if I can implement it, by points I mean the coordinates of a rectangle. Thanks again
 
Share this answer
 
Comments
10071962 5-Feb-24 2:37am    
I know, it's not simple... This is why I need your help, I'm not that advanced, I tried but it's complicated...
OriginalGriff 5-Feb-24 3:16am    
Yes, it is - so much so that I wouldn't want to reinvent the wheel and even try to duplicate it.
Instead, I'd upgrade to a much more modern version of VB that includes it: it's free for single / home / small developers after all ...
10071962 5-Feb-24 10:34am    
Just installed Visual Studio 2015. Thanks
OriginalGriff 5-Feb-24 11:05am    
:laugh:
You do realize that that one is 9 years out of date?

What's wrong with a fairly recent one? Or ... are you still running WIndows 7? :D
10071962 5-Feb-24 12:01pm    
It was the one I had available on disk to install and it supports "yield" with net 4.5, as soon as I tried it. It's fine for now, I just didn't understand how to install the offline guide. I use Windows 10. Good evening...

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900