C# 函子我应该什么时候使用它们它们的预期用途是什么

C# 函子我应该什么时候使用它们它们的预期用途是什么,c#,.net,generics,lambda,functor,C#,.net,Generics,Lambda,Functor,我就是不能把我的头绕在他们身上 据我所知,它是动态地向类添加逻辑。框架内的类是否为此做好了准备 为什么我要扩展类并在扩展中添加功能呢。我将在全球范围内访问,并且更易于维护 我读过有4种函子类型: 比较器 闭包 谓词 变压器 我们可能应该处理好每一个问题 p、 在vb中有类似的东西吗 所以我可以说,我认为lambda表达式是函子。这让我有点清醒:)(呵呵) Lambda表达式是函子吗 匿名函数是函子吗 但我问这个问题是因为我遇到了另一种类型的混蛋,即: delegate void Functo

我就是不能把我的头绕在他们身上

据我所知,它是动态地向类添加逻辑。框架内的类是否为此做好了准备

为什么我要扩展类并在扩展中添加功能呢。我将在全球范围内访问,并且更易于维护

我读过有4种函子类型:

比较器
闭包
谓词
变压器

我们可能应该处理好每一个问题

p、 在vb中有类似的东西吗

所以我可以说,我认为lambda表达式是函子。这让我有点清醒:)(呵呵)

  • Lambda表达式是函子吗
  • 匿名函数是函子吗
但我问这个问题是因为我遇到了另一种类型的混蛋,即:

delegate void FunctorDelegate(int value);
class Addition {
    FunctorDelegate _delegate;

    public Addition AddDelegate(FunctorDelegate deleg) {
        _delegate += deleg;
        return this;
    }
    public int AddAllElements(IList< int> list) {
        int runningTotal = 0;
        foreach( int value in list) {
            runningTotal += value;
            _delegate(value);
        }
        return runningTotal;
    }
}
因此,没有华丽的lambda风格的东西

现在我有了这个例子,但根本不清楚为什么这是一个“好”的解决方案

委托(函子)“在大多数情况下”是否用作lambda表达式或匿名方法,只是作为程序员的快捷方式?据我所知,只有少数情况下,它们实际上是解决问题的首选。

在.NET术语中,我认为您所描述的是
委托
——它存在于整个.NET中,而不仅仅是C

我不确定“闭包”是否与比较器/谓词/转换器的“类型”相同,因为在C#术语中,闭包只是一个实现细节,但可以是这三者中的任何一个

在.NET中,委托主要以两种方式使用:

  • 作为事件机制
  • 提供函数式编程
第一个很重要,但听起来你对第二个更感兴趣。实际上,它们的操作非常类似于单一方法接口。。。考虑:

List<int> vals = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
List<int> evenVals = vals.FindAll(i => i % 2 == 0); // predicate
List<string> valsAsStrings = vals.ConvertAll(i => i.ToString()); // transformer
// sort descending
vals.Sort((x, y) => y.CompareTo(x)); // comparer

这里的
,其中
OrderBy
方法是接受委托的LINQ扩展方法。

我确信您指的是Lambda表达式。这些都是可以快速编写的小函数,它们具有“=>”运算符的特征。这些是C#3.0的一个新特性

这个例子将是一个经典的变压器;要使用它,我们需要一个委托来定义Lambda函数的签名

delegate int Transformer(int i);
现在使用此委托声明Lambda:

int max = int.Parse(Console.ReadLine()); // perhaps 6
List<int> limited = vals.FindAll(i => i <= max);
Transformer sqr = x => x * x;
我们可以像使用普通函数一样使用它:

Console.WriteLine(sqr(3)); //9
这些在LINQ查询中经常使用,例如排序(比较器),搜索(谓词)


《C#Pocket Reference》一书(在我看来,除了是最好的一本书外,对Lambdas也有很好的了解。(ISBN 978-0-596-51922-3)

术语很有趣;我对术语“函子”的自然解释是它引用了匿名方法。因此,这将是我对它的理解

以下是我的一些典型用途:

比较(通常用于对列表进行排序):

List ints=new List();
AddRange(新的int[]{9,5,7,4,3,5,3});
排序(新比较(委托(整数x,整数y)
{
返回x.CompareTo(y);
}));
//是的,我知道ints.Sort()会产生相同的结果,但是嘿,它只是
//概念代码示例;o)
//以及较短的.NET 3.5版本:
整数排序((x,y)=>
{
返回x.CompareTo(y);
});
我将使用这种方法进行比较,而不是在它自己的方法中使用该方法的委托,在这种情况下,这种特殊的排序只发生在一个地方。如果我可能想在其他地方使用相同的比较,那么它将使用自己的、可重用的方法

我的另一个相当常见的用途是在单元测试中,当测试依赖于引发的某个事件时。我发现,在Workflow Foundation中对工作流进行单元测试时,这一点至关重要:

WorkflowRuntime runtime = WorkflowHost.Runtime;  
WorkflowInstance instance = runtime.CreateWorkflow(typeof(CreateFile)); 
EventHandler<WorkflowEventArgs> WorkflowIdledHandler = delegate(object sender, WorkflowEventArgs e)
{
    // get the ICreateFileService instance from the runtime  
    ISomeWorkflowService service = WorkflowHost.Runtime.GetService<ISomeWorkflowService>();

    // set the desired file content  
    service.DoSomeWork(instance.InstanceId, inputData);
};  
// attach event handler
runtime.WorkflowIdled += WorkflowIdledHandler;  

instance.Start();  
// perform the test, and then detach the event handler
runtime.WorkflowIdled -= WorkflowIdledHandler; 
WorkflowRuntime runtime=WorkflowHost.runtime;
WorkflowInstance实例=runtime.CreateWorkflow(typeof(CreateFile));
EventHandler WorkflowIdledHandler=委托(对象发送方,WorkflowEventArgs e)
{
//从运行时获取ICreateFileService实例
ISomeWorkflowService服务=WorkflowHost.Runtime.GetService();
//设置所需的文件内容
服务.DoSomeWork(instance.InstanceId,inputData);
};  
//附加事件处理程序
runtime.WorkflowIdled+=WorkflowIdledHandler;
instance.Start();
//执行测试,然后分离事件处理程序
runtime.WorkflowIdled-=WorkflowIdledHandler;
在这种情况下,将事件处理程序声明为匿名方法更简单,因为它使用在单元测试方法范围中定义的
实例
变量。如果我选择将事件处理程序作为它自己的独立方法来实现,我还需要找到一种方法让它获取
实例
,可能是通过引入类级成员,这在单元测试类中似乎不是一个完美的设计

我在代码中发现这种情况的情况更多,但它们通常有一到两个共同点:

  • 除了在那个特定的地方之外,我对从任何地方引用那个段代码都不感兴趣
  • 该方法需要访问超出常规方法范围的数据

    • 我认为你混淆了不同语言的术语。您似乎在C++或java感测中使用“函子”,例如。在C++中,它是一个重载函数调用运算符的类的对象,因此它可以用作函数,但可以使用状态。 这在逻辑上与C#(或任何.NET语言)中绑定到实例方法的委托相同

      写这种东西有三种方法。首先,您可以编写一个普通方法,然后将该方法的名称指定给委托变量

      void MyMethod() { Console.WriteLine("Hi!"); }
      
      void Foo()
      {
          Action a = MyMethod;
          a();
      }
      
      其次,可以使用C#2.0中引入的匿名方法语法:

      第三,可以使用C#3.0中引入的lambda语法:

      后两种方法的优点是
      List<int> ints = new List<int>();
      ints.AddRange(new int[] { 9, 5, 7, 4, 3, 5, 3 });
      ints.Sort(new Comparison<int>(delegate(int x, int y)
          {
              return x.CompareTo(y);
          }));
      // yes I am aware the ints.Sort() would yield the same result, but hey, it's just
      // a conceptual code sample ;o)
      
      // and the shorter .NET 3.5 version:
      ints.Sort((x, y) =>
      {
          return x.CompareTo(y);
      });
      
      WorkflowRuntime runtime = WorkflowHost.Runtime;  
      WorkflowInstance instance = runtime.CreateWorkflow(typeof(CreateFile)); 
      EventHandler<WorkflowEventArgs> WorkflowIdledHandler = delegate(object sender, WorkflowEventArgs e)
      {
          // get the ICreateFileService instance from the runtime  
          ISomeWorkflowService service = WorkflowHost.Runtime.GetService<ISomeWorkflowService>();
      
          // set the desired file content  
          service.DoSomeWork(instance.InstanceId, inputData);
      };  
      // attach event handler
      runtime.WorkflowIdled += WorkflowIdledHandler;  
      
      instance.Start();  
      // perform the test, and then detach the event handler
      runtime.WorkflowIdled -= WorkflowIdledHandler; 
      
      void MyMethod() { Console.WriteLine("Hi!"); }
      
      void Foo()
      {
          Action a = MyMethod;
          a();
      }
      
      void Foo()
      {
          Action a = delegate { Console.WriteLine("Hi!"); }
          a();
      }
      
      void Foo()
      {
          Action a = () => Console.WriteLine("Hi!");
          a();
      }
      
      // correct way using lambda
      button.Click += (sender, eventArgs) => MessageBox.Show("Clicked!");
      
      // compile error - wrong number of arguments
      button.Click += () => MessageBox.Show("Clicked!");
      
      // anon method, omitting arguments, works fine
      button.Click += delegate { MessageBox.Show("Clicked!"); };
      
      event EventHandler Birthday = delegate { };
      
      Func<string, int, double> f;  // takes a string and an in, returns a double
      
      var exactlyForty = people.Where(person => person.Age == 40);