Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Using the C# code below, how would you write it in Visual Basic? What is it 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's 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;
        }
    }
}
like image 855
digiguru Avatar asked May 26 '10 12:05

digiguru


1 Answers

There is none. Period. Unless you are going to write your own state machine, there is no quick fix for this. See the blog post VB.NET's "yield return" .

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

Try compiling this and take a look at the generated code with .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'm not going to copy the result, it's huge. But do take a look, you'll see that it isn't simple to solve.

like image 167
Snake Avatar answered Sep 28 '22 02:09

Snake