C# 我什么时候应该使用函子他们的预期用途是什么
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/974142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Functors when should I use them whats their intended use
提问by albertjan
I Just can't seem to wrap my head around them.
我似乎无法将头环绕在它们周围。
As I understand it's dynamically adding logic to a class. Are classes within the framework prepared for this?
据我了解,它正在向类动态添加逻辑。框架内的类是否为此做好了准备?
Why should I just extend the class and add the functionality to it in the extension. I would be globally accessible and afaik much easier to maintain.
为什么我要扩展该类并在扩展中为其添加功能。我可以在全球范围内访问,并且更容易维护。
I've Read there are 4 functor types:
我读过有 4 种函子类型:
Comparer
Closure
Predicate
Transformer
比较器
闭包
谓词
转换器
We should probably Handle each one of them.
我们可能应该处理它们中的每一个。
p.s. is there something like it in vb?
ps 在 vb 中有类似的东西吗?
So I can state I think that lambda expressions are functors. This clears up things for me a bit :) (hehe)
所以我可以声明我认为 lambda 表达式是函子。这让我有点明白了:)(呵呵)
- Lambda expressions are functors?
- Anonymous functions are functors?
- Lambda 表达式是函子吗?
- 匿名函数是函子吗?
But I asked this question because I ran into another type of fucntors namely these ones:
但我问这个问题是因为我遇到了另一种类型的 fucntor,即这些:
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;
}
}
And then calling it with this:
然后用这个调用它:
int runningTotal = new Addition()
.AddDelegate(new FunctorDelegate(
delegate(int value) {
if ((value % 2) == 1) {
runningOddTotal += value;
}
}))
.AddDelegate(new FunctorDelegate(
delegate(int value) {
if ((value % 2) == 0) {
runningEvenTotal += value;
}
}))
.AddAllElements(list);
So no fancy lambda style things.
所以没有花哨的 lambda 风格的东西。
Now I have this example but it isn't at all clear why this is a "good" solution.
现在我有了这个例子,但完全不清楚为什么这是一个“好”的解决方案。
Are delegates (functors) used as lambda expressions or anonymous methods "in most cases" just there as a shortcut for the programmer? There are as far as I can see only a few cases where they're actually the prefered choice for a problem.
委托(函子)是否“在大多数情况下”用作 lambda 表达式或匿名方法只是作为程序员的快捷方式?据我所知,只有少数情况下它们实际上是解决问题的首选。
采纳答案by Daniel Earwicker
I think you're confusing terms from different languages. You seem to be using "Functor" in the C++ or Java sense, e.g. see the wikipedia page. In C++, it's an object of a class that overloads the function-call operator, so it can be used as a function but with state.
我认为您混淆了来自不同语言的术语。您似乎在使用 C++ 或 Java 意义上的“Functor”,例如,请参阅维基百科页面。在 C++ 中,它是重载函数调用运算符的类的对象,因此它可以用作函数但带有状态。
This is logically the same thing as a delegate bound to an instance method in C# (or any .NET language).
这在逻辑上与绑定到 C#(或任何 .NET 语言)中的实例方法的委托相同。
There are three ways to write such a thing. First, you can write an ordinary method, and then assign the name of the method to a delegate variable.
有三种方法可以写这样的东西。首先可以写一个普通的方法,然后将方法名赋值给一个委托变量。
void MyMethod() { Console.WriteLine("Hi!"); }
void Foo()
{
Action a = MyMethod;
a();
}
Second, you can use anonymous method syntax, introduced in C# 2.0:
其次,您可以使用 C# 2.0 中引入的匿名方法语法:
void Foo()
{
Action a = delegate { Console.WriteLine("Hi!"); }
a();
}
Thirdly, you can use lambda syntax, introduced in C# 3.0:
第三,您可以使用 C# 3.0 中引入的 lambda 语法:
void Foo()
{
Action a = () => Console.WriteLine("Hi!");
a();
}
The advantage of the last two is that the body of the method can read and write local variables in the containing method.
后两者的优点是方法体可以读写包含方法中的局部变量。
The advantage of lambda syntax over anon-methods are that it is more succinct and it does type inference on parameters.
与匿名方法相比,lambda 语法的优势在于它更简洁,并且可以对参数进行类型推断。
Update:The advantage of anon-methods (delegate
keyword) over lambdas is that you can omit the parameters altogether if you don't need them:
更新:匿名方法(delegate
关键字)相对于 lambda 的优势在于,如果您不需要它们,您可以完全省略参数:
// 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!"); };
I know of only one situation where this is worth knowing, which is when initializing an event so that you don't have to check for null
before firing it:
我只知道一种值得了解的情况,即初始化事件时,这样您就不必null
在触发它之前检查:
event EventHandler Birthday = delegate { };
Avoids a lot of nonsense elsewhere.
避免了很多其他地方的废话。
Finally, you mention that there are four kinds of functor. In fact there are an infinity of possibly delegate types, although some authors may have their favourites and there obviously will be some common patterns. An Action
or Command
takes no parameters and returns void
, and a predicate takes an instance of some type and returns true
or false
.
最后,你提到有四种函子。事实上,可能的委托类型有无数种,尽管有些作者可能有他们的最爱,并且显然会有一些共同的模式。一个Action
或Command
不带参数,返回void
,和一个谓语需要一些类型并返回的一个实例true
或false
。
In C# 3.0, you can whip up a delegate with up to four parameters of any types you like:
在 C# 3.0 中,您可以使用最多四个您喜欢的任何类型的参数创建一个委托:
Func<string, int, double> f; // takes a string and an in, returns a double
Re: Updated Question
回复:更新的问题
You ask (I think) if there are many use cases for lambdas. There are more than can possibly be listed!
你问(我认为)是否有很多 lambda 用例。有更多可能列出!
You most often see them in the middle of larger expressions that operate on sequences (lists computed on-the-fly). Suppose I have a list of people, and I want a list of people exactly forty years old:
您最常在对序列(即时计算的列表)进行操作的较大表达式的中间看到它们。假设我有一个人的名单,我想要一个刚好四十岁的人的名单:
var exactlyForty = people.Where(person => person.Age == 40);
The Where
method is an extension method on the IEnumerable<T>
interface, where T
in this case is some kind of Person
class.
该Where
方法是IEnumerable<T>
接口上的扩展方法,T
在这种情况下是某种Person
类。
This is known in .NET as "Linq to Objects", but known elsewhere as pure functional programming on sequences or streams or "lazy" lists (all different names for the same thing).
这在 .NET 中称为“Linq to Objects”,但在其他地方称为序列或流或“惰性”列表(同一事物的所有不同名称)上的纯函数式编程。
回答by Marc Gravell
In .NET terms, I thinkwhat you are describing is the Delegate
- and it exists in all of .NET, not just C#.
在 .NET 术语中,我认为您所描述的是Delegate
- 它存在于所有 .NET 中,而不仅仅是 C#。
I'm not sure that a "closure" would a "type" in the same was as a comparer/predicate/transformer, since in C# terms a closure is simply an implementation detail but can beany of those three.
我不确定“闭包”是否与比较器/谓词/转换器一样是“类型”,因为在 C# 术语中,闭包只是一个实现细节,但可以是这三个中的任何一个。
In .NET, delegates are used in two main ways:
在 .NET 中,委托主要有两种使用方式:
- as the eventing mechanism
- to provide functional-style programming
- 作为事件机制
- 提供函数式编程
The first is important, but it sounds like you are more interested in the second. In reality, they operate much like single-method interfaces... consider:
第一个很重要,但听起来您对第二个更感兴趣。实际上,它们的操作很像单方法接口……考虑:
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
A closure is more where we bring additional scope from outsidethe delegate intothe delegate:
闭包更像是我们将委托外部的额外范围引入委托的地方:
int max = int.Parse(Console.ReadLine()); // perhaps 6
List<int> limited = vals.FindAll(i => i <= max);
here the max
is captured into the delegate as a closure.
这里max
作为闭包被捕获到委托中。
Re "Are classes within the framework prepaired for this?" - many are, and LINQ goes a longway to allowing this even wider. LINQ provides extension methods over (for example) all of IEnumerable<T>
- meaning that collections withoutdelegate-based access aquire them for free:
重新“框架内的类是否为此做好了准备?” -许多都是和LINQ走一段很长的方式来让这个更广泛。LINQ 提供了(例如)所有的扩展方法IEnumerable<T>
- 这意味着没有基于委托的访问的集合可以免费获取它们:
int[] data = { 1,2,3,4,5,6,7,8,9 };
var oddData = data.Where( i => i % 2 == 1 );
var descending = data.OrderBy(i => -i);
var asStrings = data.Select(i => i.ToString());
Here the Where
and OrderBy
methods are LINQ extension methods that take delegates.
这里的Where
和OrderBy
方法是接受委托的 LINQ 扩展方法。
回答by wsd
I'm sure you mean Lambda Expressions. Those are Small Functions you can write very quickly, and they have the characteristic "=>" Operator. These are a new Feature of C# 3.0.
我确定您指的是 Lambda 表达式。这些是您可以非常快速地编写的小函数,它们具有特征性的“=>”运算符。这些是 C# 3.0 的新功能。
This Example will be a classic Transformer; to use one we need a delegate to define the signature for the Lambda Function.
这个例子将是一个经典的 Transformer;要使用一个,我们需要一个委托来定义 Lambda 函数的签名。
delegate int Transformer(int i);
Now Declare a Lambda with this delegate:
现在用这个委托声明一个 Lambda:
Transformer sqr = x => x * x;
We can use it like a normal function:
我们可以像普通函数一样使用它:
Console.WriteLine(sqr(3)); //9
These are used in LINQ Queries a lot, for example to Sort (Comparer), to Search through (Predicate).
这些在 LINQ 查询中使用很多,例如排序(比较器),搜索(谓词)。
The book "C# Pocket Reference" (apart from beign the best around in my opinion, has a very good part on Lambdas. (ISBN 978-0-596-51922-3 )
《C# Pocket Reference》这本书(除了在我看来最好的周围,在 Lambdas 上有很好的部分。(ISBN 978-0-596-51922-3)
回答by Fredrik M?rk
Interesting with terminology; my spontaneous interpretation of the term "Functor" was that it referred to anonymous methods. So that will be my take on it.
有趣的术语;我对“函子”一词的自发解释是它指的是匿名方法。所以这将是我的看法。
These are some of my typical uses:
这些是我的一些典型用途:
Comparisons (usually for sorting a list):
比较(通常用于对列表进行排序):
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);
});
I will use this approach for comparisons, rather than having it in its own method an using a delegate for that method, in the cases where this particular sort happens in one place only. If it is likely that I will want to use the same comparison somewhere else, it gets to live in its own, reusable method.
我将使用这种方法进行比较,而不是在它自己的方法中使用该方法的委托,在这种特殊类型仅发生在一个地方的情况下。如果我可能想在其他地方使用相同的比较,它就会以自己的、可重用的方法存在。
Another of my fairly common uses is in unit testing, when the test relies on some event being raised. I have found that to be essential when unit testing workflows in Workflow Foundation:
我的另一个相当常见的用途是在单元测试中,当测试依赖于引发的某些事件时。我发现在 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;
In this case it is simpler to have the event handler declared as anonymous methods since it uses the instance
variable that is defined in the unit test method scope. Had I intstead opted to implelment the event handler as its own separate method I would also need to figure out a way for it to pick up instance
, probably by introducing a class level member, which would not seem like a perfect design in a unit test class.
在这种情况下,将事件处理程序声明为匿名方法会更简单,因为它使用instance
在单元测试方法范围中定义的变量。如果我选择将事件处理程序作为它自己的单独方法来实现,我还需要找出一种方法来让它接收instance
,可能是通过引入一个类级别的成员,这在单元测试类中似乎不是一个完美的设计.
There are more cases where I find this in my code, but they usually have one or two things in common:
在更多情况下,我在我的代码中发现了这一点,但它们通常有一两个共同点:
- I have no interest in referencing that piece of code from anywhere else than in that particular place.
- The method needs access to data that would be out of the scope for a regular method
- 除了那个特定的地方,我没有兴趣从其他任何地方引用那段代码。
- 该方法需要访问超出常规方法范围的数据
回答by nomen
The real answer is that a functor is a type of mathematical object, and is "reified" by different languages in different ways. For example, suppose that you have a "container" object that stores a bunch of other objects of the same type. (For example, a set or array) Then, if your language had a method that let you 'map' over the container, so that you could call a method on each object in the container, then the container would be a functor.
真正的答案是,函子是一种数学对象,被不同的语言以不同的方式“具体化”。例如,假设您有一个“容器”对象,其中存储了一堆相同类型的其他对象。(例如,一个集合或数组)然后,如果您的语言有一个方法可以让您“映射”容器,以便您可以对容器中的每个对象调用一个方法,那么容器将是一个 functor。
In other words, a functor is a container with a method that lets you pass a method to its contained things.
换句话说,函子是一个带有方法的容器,可以让你将方法传递给它所包含的东西。
Every language has its own way of doing this, and they sometimes conflate the usage. For example, C++ uses function pointers to represent the "passing in" of a method, and calls the function pointer a "functor." Delegates are just a handle on methods that you can pass in. You are using the terminology "incorrectly", just like C++ does.
每种语言都有自己的方式来做到这一点,他们有时会混淆用法。例如,C++ 使用函数指针来表示方法的“传入”,并将函数指针称为“函子”。委托只是您可以传入的方法的句柄。您正在“错误地”使用术语,就像 C++ 一样。
Haskell gets it right. You declare that a type implements the functor interface, and then you get the mapping method.
Haskell 做对了。你声明一个类型实现了函子接口,然后你得到了映射方法。
Functions (like lambdas) are functors too, but it can be kind of hard to think of a function as a "container". In short, a function is a "container" around a return value, constructed in such a way that the return value (possibly) depends on the function's arguments.
函数(如 lambda 表达式)也是函子,但很难将函数视为“容器”。简而言之,函数是一个围绕返回值的“容器”,其构造方式使得返回值(可能)取决于函数的参数。