如何使用Func键<>和Action <>设计应用程序时?(How do y

2019-07-21 10:52发布

我可以找到有关Func键<>和Action <>所有的例子都是简单的 ,如下面的一个,你看他们是如何在技术上的工作,但我希望看到他们在哪里,他们解决了以前无法得到解决或能问题的例子使用只有在一个更复杂的方式,即我知道他们是如何工作的,我可以看到他们是简洁而强大的解决,所以我想了解他们,他们解决什么样的问题, 更大的意义上 ,我怎么可能会在使用它们应用设计。

以何种方式(模式),你用Func键<>和行动<>解决实际问题?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestFunc8282
{
    class Program
    {
        static void Main(string[] args)
        {
            //func with delegate
            Func<string, string> convert = delegate(string s)
            {
                return s.ToUpper();
            };

            //func with lambda
            Func<string, string> convert2 = s => s.Substring(3, 10);

            //action
            Action<int,string> recordIt = (i,title) =>
                {
                    Console.WriteLine("--- {0}:",title);
                    Console.WriteLine("Adding five to {0}:", i);
                    Console.WriteLine(i + 5);
                };

            Console.WriteLine(convert("This is the first test."));
            Console.WriteLine(convert2("This is the second test."));
            recordIt(5, "First one");
            recordIt(3, "Second one");

            Console.ReadLine();

        }
    }
}

Answer 1:

他们也得心应手重构switch语句。

采取以下(虽然简单)例如:

public void Move(int distance, Direction direction)
{
    switch (direction)
    {
        case Direction.Up :
            Position.Y += distance;
            break;
        case Direction.Down:
            Position.Y -= distance;
            break;
        case Direction.Left:
            Position.X -= distance;
            break;
        case Direction.Right:
            Position.X += distance;
            break;
    }
}

与动作的委托,您可以按如下重构它:

static Something()
{
    _directionMap = new Dictionary<Direction, Action<Position, int>>
    {
        { Direction.Up,    (position, distance) => position.Y +=  distance },
        { Direction.Down,  (position, distance) => position.Y -=  distance },
        { Direction.Left,  (position, distance) => position.X -=  distance },
        { Direction.Right, (position, distance) => position.X +=  distance },
    };
}

public void Move(int distance, Direction direction)
{
    _directionMap[direction](this.Position, distance);
}


Answer 2:

使用LINQ。

List<int> list = { 1, 2, 3, 4 };

var even = list.Where(i => i % 2);

该参数Where是一个Func<int, bool>

Lambda表达式是我最喜欢的C#部分之一。 :)



Answer 3:

我用的是ActionFunc代表所有的时间。 我通常与lambda语法声明它们以节省空间,并利用它们主要是为了减少大型方法的大小。 当我回顾我的方法,有时代码段类似于将脱颖而出。 在这种情况下,我包了类似的代码段为ActionFunc 。 使用委托减少冗余代码,给一个不错的签名代码段,并可以很容易地被提升到一个方法,如果需要的话。

我以前写的Delphi代码,你可以在函数内声明的函数。 Action和Func键完成在C#对于我这种相同的行为。

这里有一个重新定位委托控件的示例:

private void Form1_Load(object sender, EventArgs e)
{
    //adjust control positions without delegate
    int left = 24;

    label1.Left = left;
    left += label1.Width + 24;

    button1.Left = left;
    left += button1.Width + 24;

    checkBox1.Left = left;
    left += checkBox1.Width + 24;

    //adjust control positions with delegate. better
    left = 24;
    Action<Control> moveLeft = c => 
    {
        c.Left = left;
        left += c.Width + 24; 
    };
    moveLeft(label1);
    moveLeft(button1);
    moveLeft(checkBox1);
}


Answer 4:

有一件事我用它是永远不会改变给予相同的输入昂贵的方法调用缓存:

public static Func<TArgument, TResult> Memoize<TArgument, TResult>(this Func<TArgument, TResult> f)
{
    Dictionary<TArgument, TResult> values;

    var methodDictionaries = new Dictionary<string, Dictionary<TArgument, TResult>>();

    var name = f.Method.Name;
    if (!methodDictionaries.TryGetValue(name, out values))
    {
        values = new Dictionary<TArgument, TResult>();

        methodDictionaries.Add(name, values);
    }

    return a =>
    {
        TResult value;

        if (!values.TryGetValue(a, out value))
        {
            value = f(a);
            values.Add(a, value);
        }

        return value;
    };
}

默认递归斐波那契数例如:

class Foo
{
  public Func<int,int> Fibonacci = (n) =>
  {
    return n > 1 ? Fibonacci(n-1) + Fibonacci(n-2) : n;
  };

  public Foo()
  {
    Fibonacci = Fibonacci.Memoize();

    for (int i=0; i<50; i++)
      Console.WriteLine(Fibonacci(i));
  }
}


Answer 5:

不知道,如果是坏的形式回答同样的问题两次或没有,但得到一些想法,这些类型一般我建议阅读关于函数式编程杰里米米勒的MSDN文章的更好的用途:

对于日常.NET开发函数式编程



Answer 6:

我用一个动作很好地封装在一个事务中执行数据库操作:

public class InTran
{
    protected virtual string ConnString
    {
        get { return ConfigurationManager.AppSettings["YourDBConnString"]; }
    }

    public void Exec(Action<DBTransaction> a)
    {
        using (var dbTran = new DBTransaction(ConnString))
        {
            try
            {
                a(dbTran);
                dbTran.Commit();
            }
            catch
            {
                dbTran.Rollback();
                throw;
            }
        }
    }
}

我们在一个事务中,我只是做执行

new InTran().Exec(tran => ...some SQL operation...);

该INTRAN类可以驻留在一个公共库,减少重复和为将来的功能调整提供了烧毛位置。



Answer 7:

通过保持他们通用的,支持多种参数,它可以让我们避免创建做同样的事情强类型的代表或冗余的代表。



Answer 8:

其实,我发现这个在计算器(至少 - 的想法):

public static T Get<T>  
    (string cacheKey, HttpContextBase context, Func<T> getItemCallback)
            where T : class
{
    T item = Get<T>(cacheKey, context);
    if (item == null) {
        item = getItemCallback();
        context.Cache.Insert(cacheKey, item);
    }

    return item;
}


Answer 9:

我有一个接受一个通用的Func键或在构造函数中的动作,以及一些文本的独立形式。 它在一个单独的线程执行功能/动作,同时显示在表格一些文本并显示动画。

这是我个人的Util库,我用它,每当我想要做一个中等长度的操作,并阻止非侵入性的方式的UI。

我认为把一个进度条的形式为好,以便它能够执行更长的运行操作,但我还没有真正需要它呢。



文章来源: How do you use Func<> and Action<> when designing applications?