yield keyword to digest code block like Ruby

In Ruby, we can yield the code block from other scope, in order to optimize the amount of writing code:

  def get_resource(published=true)
    find_resources do
      if I18n.locale == :ar && @resource_slug == "home"
        Resource.find_by_slug("home")
      else
        ResourceType.find_by_slug(@type_slug).resources.send(
          published ? :published : :unpublished
        ).find_by_slug(@resource_slug)
      end
    end
  end

  def get_resources(published=true)
    find_resources do
      ResourceType.includes(:resources).find_by_slug(@type_slug).resources.send(
        published ? :published : :unpublished
      )
    end
  end

  def find_resources
    begin
      @type_slug, @resource_slug = params[:type], params[:resource]
      yield
    rescue Mongoid::Errors::DocumentNotFound, NoMethodError
      nil
    end
  end

In C#, we also have yield keyword. Here is the example taken from documentation:

//using System.Collections;  
//using System.Diagnostics; 
public static void Process()
{
    // Display powers of 2 up to the exponent of 8:  
    foreach (int number in Power(2, 8))
    {
        Debug.Write(number.ToString() + " ");
    }
    // Output: 2 4 8 16 32 64 128 256
}


public static IEnumerable Power(int baseNumber, int highExponent)
{
    int result = 1;

    for (int counter = 1; counter <= highExponent; counter++)
    {
        result = result * baseNumber;
        yield return result;
    }
}

The C# yield seems to be the way to return interim result from the iterative method, as opposed to Ruby's way of literally stamping the entire code block into specified region at runtime.

Is there a similar technique of writting less code in C# using yield keyword? For an instance:

public class EntityBase 
{

   // Generic Try-Catch function, so we never have to write this block in our code

   public object GenericTryCatch()
    {
        try
        {
            // yield here
        }
        catch(Exception except)
        {
            Logger.log(except.Message);
        }
        finally
        {
            // return the control to the caller function
        }

        return null;

    }
}
Jon Skeet
people
quotationmark

I don't know Ruby, but it looks like basically you want to pass "some code to execute" - which is typically done in C# with a delegate (or an interface, for a specific meaning of course). As far as I can see, yield in Ruby is entirely different to yield return in C#. If you don't have any parameters or a return value, the Action delegate is suitable. You can then call the method using any approach to create a delegate, such as:

  • An existing method, either through a method group conversion or an explicit delegate creation expression
  • A lambda expression
  • An anonymous method

For example:

Foo(() => Console.WriteLine("Called!"));

...


static void Foo(Action action)
{
    Console.WriteLine("In Foo");
    action();
    Console.WriteLine("In Foo again");
    action();
}

There's a lot to learn about delegates - I don't have time to go into them in detail right now, unfortunately, but I suggest you find a good book about C# and learn about them from that. (In particular, the fact that they can accept parameters and return values is crucial in various situations, including LINQ.)

people

See more on this question at Stackoverflow