What is the equivalent syntax in VB.NET for "yield return"?

Using C # below, how would you write it in Visual Basic? What is he trying to say?

using System; using System.Collections.Generic; using System.IO; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; namespace Microsoft.LiveLabs.Pivot { /// <summary> /// Tile Builder class /// </summary> public static class TileBuilder { /// <summary> /// Specifies which images are required in the images array used in CreateTile /// according to the Morton fractal pattern used by Seadragon. /// </summary> /// <remarks> /// Usage of this and CreateTile are kind of tricky. Here an example: /// Say you have a results set that is a collection of items like so: { item1, item2, ..., item100 } /// Since Seadragon expects the tiles to be laid out in a Morton pattern, /// level 6 will look like the following: /// /// -------------------------- /// |0 1 4 5 | 16 17... /// |2 3 6 7 | 18 19 /// |8 9 12 13 | 24 25 /// |10 11 14 15 | 26 27 /// |----------------------- /// |32 33 36 37 | 48 49 /// |34 35 38 39 | 50 51... /// |. . /// |. . /// . . /// /// Each tile at level 6 is 4x4, so the dashes represent tile boundaries. Now, say /// you want to build 0,0. You need the images on that tile. The ids 0, 1, 4, 5... /// represent the ids in your result set, { item1, item2, ..., item100 }. Calling /// this method tells you the ids to use for a given tile. You then must retrieve /// the necessary images out the result set, and supply them in the order this /// method gave you to CreateTile. This will result in a correctly built tile /// that Seadragon can use. /// </remarks> /// <param name="imageCount">Number of images in the full set.</param> /// <param name="level">The level to which each image will be downsampled.</param> /// <param name="row">The row number which specifies what images to render.</param> /// <param name="column">The row number which specifies what images to render.</param> /// <param name="tileSize">The size of the tile to return.</param> public static IEnumerable<int> GetTileIds( int imageCount, int level, int row, int column, int tileSize) { // Calculate upper-left hand corner of tile in image space (1 unit = 1 image) int levelSize = (int)Math.Pow(2, level); int imagePerSide = tileSize / levelSize; int xOffset = row * imagePerSide; int yOffset = column * imagePerSide; if (imagePerSide <= 0) { throw new ArgumentOutOfRangeException("Level is greater than the maximum depth allowed by the tile size, or the tile size is 0."); } // Loop through x and y in image space, starting at the upper-left // hand corner of the tile. Find all ids on the given tile. for (int x = 0; x < imagePerSide; x++) { for (int y = 0; y < imagePerSide; y++) { int n = XYToMorton(x + xOffset, y + yOffset); if (n < imageCount) { yield return n; } } } } /// <summary> /// Create a tile for a collection according to the Morton fractal /// pattern used by Seadragon. /// </summary> /// <remarks> /// See GetTileIds for more information. /// </remarks> /// <param name="imageCount">The total number of images in the collection.</param> /// <param name="images">Jpeg images to render on this tile. /// If this is null, a blank tile will be returned. /// See GetTileIds remarks for more information.</param> /// <param name="level">The level to which each image will be downsampled.</param> /// <param name="row">The row number which specifies what images to render.</param> /// <param name="column">The row number which specifies what images to render.</param> /// <param name="tileSize">The size of the tile to return.</param> /// <param name="output">The stream to use to output the result.</param> public static void CreateTile( int imageCount, IEnumerable<ImageBag> images, int level, int row, int column, int tileSize, string fileType, Stream output) { // Calculate upper-left hand corner of tile in image space (1 unit = 1 image). int levelSize = (int)Math.Pow(2, level); int imagePerSide = tileSize / levelSize; int xOffset = row * imagePerSide; int yOffset = column * imagePerSide; if (imagePerSide <= 0) { throw new ArgumentOutOfRangeException("Level is greater than the maximum depth allowed by the tile size, or the tile size is 0."); } if (output == null) { throw new ArgumentNullException("The given output stream is null."); } // Create the tile. WriteableBitmap outputBitmap = new WriteableBitmap( tileSize, tileSize, 96, 96, PixelFormats.Bgr24, null); // If images is null, return a blank tile. if (images != null) { // Loop through the tile in relative x and y image-space. IEnumerator<ImageBag> imageEnumerator = images.GetEnumerator(); for (int x = 0; x < imagePerSide; x++) { for (int y = 0; y < imagePerSide; y++) { // Convert to Morton id-space from the absolute image-space (to get absolute, add offsets). int n = XYToMorton(x + xOffset, y + yOffset); if (n < imageCount) { if (imageEnumerator.MoveNext()) { if (imageEnumerator.Current == null) { continue; } // Compute the pixel location int locX = levelSize * x; int locY = levelSize * y; int width = 0; int height = 0; imageEnumerator.Current.ImageSize(out width, out height); MemoryStream imageStream = new MemoryStream(imageEnumerator.Current.ImageData); // Determine the largest tile size to the nearest power of two for // this image: 2^ceil(lg max(width, height)). double maxTileSize = Math.Pow(2, Math.Ceiling(Math.Log(Math.Max(width, height), 2))); // Downsample to the correct size and decompress the image. The correct size // is total dimenion of the image * level size / max tile size required for // total width. Think of this as dividing the dimensions by two foreach // levels, starting at the max tile size, and going up to the current // tile size TransformedBitmap downsampledImage = JpegDecoder.DownsampleJpeg( imageStream, Math.Ceiling(width * levelSize / maxTileSize), Math.Ceiling(height * levelSize / maxTileSize)); // Copy the pixels to a buffer and then write them to the // appropriate region on the output image. int stride = (downsampledImage.PixelWidth * downsampledImage.Format.BitsPerPixel + 7) / 8; byte[] buffer = new byte[stride * downsampledImage.PixelHeight]; downsampledImage.CopyPixels(buffer, stride, 0); Int32Rect outputRect = new Int32Rect(locX, locY, downsampledImage.PixelWidth, downsampledImage.PixelHeight); outputBitmap.WritePixels(outputRect, buffer, stride, 0); } else { // We should render the image, but we're done with our list. // So, exit both loops. x = imagePerSide; y = imagePerSide; } } else { // Since n is monotonic wrt y, we know y has gone too far down, so // we can reset it. y = imagePerSide; } } } } // Write the output BitmapFrame outputFrame = BitmapFrame.Create(outputBitmap); BitmapEncoder encoder = new JpegBitmapEncoder(); encoder.Frames.Add(outputFrame); encoder.Save(output); } /// <summary> /// Converts an x and y to a Morton number /// </summary> /// <param name="x">x location to convert.</param> /// <param name="y">y location to convert.</param> /// <returns>Returns the morton number which corresponds to the /// given x and y coordinates.</returns> private static int XYToMorton(int x, int y) { const uint BITS_PER_BYTE = 8; const uint BIT_PAIRS = sizeof(int) * BITS_PER_BYTE / 2; int morton = 0; for (int i = 0; i < BIT_PAIRS; i++) { morton |= (x & 1) << (i * 2); morton |= (y & 1) << ((i * 2) + 1); x >>= 1; y >>= 1; } return morton; } } } 
+4
source share
6 answers

FROM#:

 yield return scriptRef 

VB.NET:

 Return New List(Of ScriptReference) From {scriptRef} 
-8
source

Not. Period. If you are not going to write your own automaton, there is no quick fix for this. See the VB.NET blog post "return return" .

For those who care about what is actually generated (yes, I like the C # precompiler and compiler :)):

Try compiling and take a look at the generated code using .NET Reflector or something:

 class Program { static void Main(string[] args) { var foo = new Foo(); foreach(var result in foo.Bar()) { Console.WriteLine(result); } Console.ReadLine(); } } class Foo { public IEnumerable<char> Bar() { const char start = 'a'; for(int x = 0;x < 26;x++) { yield return (char)(start + x); } } } 

I am not going to copy the result, it is huge. But look, you will see that this is not easy to solve.

+16
source

There is no exact duplicate yield in VB. It would be best to create a collection that is in yield ed and return it in its entirety so that the call code goes over. This is not exactly the same as the code you provided, but it should have the same overall effect. yield is essentially just syntactic sugar for returning parts of a collection to the foreach one at a time to optimize runtime and allow for early breaks (if you decide you don't need to list everything in the end).

+3
source

A block of code with yield return / yield break is called an iterator . This function does not exist in VB. Of course, you can "translate" this code, but it is not very simple ... you need to create your own class that implements IEnumerator(Of Integer) in order to reproduce exactly the same behavior:

  • Initialize it using the parameters of the original function
  • Implement loop logic in the MoveNext method, storing loop variables in private fields. This method should also set a field to store the current value ( n in the original function)
  • Returns the current value from the Current property.
  • Reset loop variables in the Reset method
  • Do nothing in the Dispose method

It is doable, but honestly, it’s a pain ...

Another, simpler option is to populate List(Of Integer) results and return this list: just replace yield return n with list.Add(n)

+3
source

There is no yield return equivalent in VB.NET, but it can be emulated.

See the Stack Overflow question Exiting in VB.NET and its answers.

Perhaps Visual Studio Magazine Using Iterators in VB Now will help.

+1
source

Not. However, you can create it.
Create an iterator class.
A few steps for this:

  • Create a function that is basically an iteration step. The function must accept any arguments necessary for each calculation, and return arguments for the next calculation. (in order to realize the output gap, as well as return the income, this function should also be able to return some logical marking of the end).
  • Create a class that implements IEnumerator. The Current property should return the latest calculated value, Reset should Reset all the values ​​to their original values, and the MoveNext function should calculate the next value, and if the computational function returns false, return the false itself.

For extra credit, make the class general and able to work with any function provided by the delegate.
You can simplify this a bit and make MoveNext itself a calculation function, but this way it is easy to create different iterators from the same class implementation.

+1
source

Source: https://habr.com/ru/post/1310962/


All Articles