【问题标题】:yield keyword to digest code block like Rubyyield 关键字来消化像 Ruby 一样的代码块
【发布时间】:2013-09-29 07:16:14
【问题描述】:

在 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 关键字。这是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;
    }
}

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;

    }
}

【问题讨论】:

    标签: c# .net syntax


    【解决方案1】:

    我不了解 Ruby,但看起来基本上你想传递“一些要执行的代码”——这通常在 C# 中通过委托(或接口,当然是为了特定含义)来完成。据我所知,Ruby 中的yield 与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。)

    【讨论】:

    • 感谢您的解释和建议。
    • OP 应该会因为找到 Jon Skeet 不知道的东西而获奖 ;-)
    【解决方案2】:

    我对 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
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-10
      • 2011-05-18
      • 1970-01-01
      • 1970-01-01
      • 2011-09-18
      • 2011-02-27
      • 2011-02-10
      • 2015-03-26
      相关资源
      最近更新 更多