2

在 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

在 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;
    }
}

C# yield 似乎是从迭代方法返回中间结果的方式,而不是 Ruby 在运行时将整个代码块直接标记到指定区域的方式。

是否有类似的技术可以使用 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;

    }
}
4

2 回答 2

5

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

  • 现有方法,通过方法组转换或显式委托创建表达式
  • 一个 lambda 表达式
  • 匿名方法

例如:

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

...


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

有很多关于委托的知识 - 不幸的是,我现在没有时间详细介绍它们,但我建议你找一本关于 C# 的好书并从中了解它们。(特别是,它们可以接受参数和返回值这一事实在各种情况下至关重要,包括 LINQ。)

于 2013-09-29T07:21:31.023 回答
4

我对 Ruby 的有限了解告诉我,您只需要某种委托:

void SomeMethod(Action action) {
    // do some stuff here
    action(); // the equivalent (that I can see) of yield
}

用法:

SomeMethod(() => {
    // method that is called when execution hits "action()" above
});
于 2013-09-29T07:22:37.387 回答