yield关键字来消化像Ruby这样的代码块

Ann*_*nie 2 .net c# syntax

在Ruby中,我们可以从其他范围生成代码块,以优化编写代码的数量:

  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
Run Code Online (Sandbox Code Playgroud)

在C#中,我们还有yield关键字。这是来自文档的示例:

//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;
    }
}
Run Code Online (Sandbox Code Playgroud)

与Ruby在运行时将整个代码块逐字地标记到指定区域中的方法相反,C#yield似乎是从迭代方法返回临时结果的方法。

是否存在使用yield关键字在C#中编写更少代码的类似技术?对于一个实例:

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;

    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

我不了解Ruby,但看起来基本上您想传递“一些要执行的代码”-通常在C#中使用委托(或接口,当然有特定含义)来完成。据我所知,yieldRuby与yield returnC#完全不同。如果您没有任何参数或返回值,Action则适合使用委托。然后,您可以使用任何方法来创建委托的方法,例如:

  • 通过方法组转换或显式委托创建表达式的现有方法
  • Lambda表达式
  • 匿名方法

例如:

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

...


static void Foo(Action action)
{
    Console.WriteLine("In Foo");
    action();
    Console.WriteLine("In Foo again");
    action();
}
Run Code Online (Sandbox Code Playgroud)

关于委托,有很多东西要学习-不幸的是,我现在没有时间详细讨论委托,但是我建议您找到一本有关C#的好书,并从中学习有关委托的知识。(尤其是它们可以接受参数和返回值的事实在包括LINQ在内的各种情况下都是至关重要的。)