因此,当我返回一个对象时,我认为它将内存地址返回给您可以引用和使用的对象(或包含内存地址的对象)。
但是当你返回一个函数时实际发生了什么?
您的应用如何知道该func使用哪个对象实例?
我的直觉告诉我,对象实例引用与func一起传递,但实际发生的是什么?
我似乎无法在这个主题上找到太多。
修改: 为了澄清,我问一个方法何时返回一个函数
答案 0 :(得分:6)
Func
是委托 - 一种与特定方法签名关联的对象,通常绑定到具有该签名的特定方法。这可能是static
或实例方法,它可能是通用的或不是通用的;在所有情况下,委托实例都包含调用该方法所需的所有信息。
答案 1 :(得分:5)
Func
是一个委托,Delegate
个实例封装了一个MethodInfo
和一个可选的目标对象,以便在调用时调用该方法。
答案 2 :(得分:2)
Func<T>
只是一名代表。如果它被设置为实例方法,那么,它[神奇地]在调用时获得正确的this
值。如果设置为静态方法,则没有this
。如果将其设置为closure / lambda,则闭包会在关闭时“捕获”范围内的变量。词汇范围(有一些警告:事情并不总是以你认为的方式运作)。
编辑添加:
来自C#标准,ISO 23270:2006 信息技术 - 编程语言 - C#,§8.10:
8.10代表
代理启用其他语言通过函数解决的方案 指针。但是,与函数指针不同,委托是面向对象的,类型安全的。
委托声明定义了一个派生自类
System.Delegate
的类。 委托实例封装了一个或多个方法,每个方法都被称为 可调用实体 。例如,方法,可调用实体由实例组成 和该实例上的方法。对于静态方法,可调用实体由just组成 一个方法。给定一个委托实例和一组适当的参数,可以调用 所有委托实例的方法都包含那组参数。
更详细地说,另一个标准,ISO 23271:2006 信息技术 - 公共语言基础结构(CLI)分区I到VI 在§14.6中说明:
实例构造函数(名为
.ctor
并标记为specialname
和rtspecialname
, 参见§10.5.1)应该采用两个参数,第一个参数类型为System.Object
, 第二个类型为System.IntPtr
。实际调用时(通过newobj
指令,参见Partition III),第一个参数应该是类的一个实例 (或其派生类之一)定义目标方法,第二个参数 应该是一个指向要调用的方法的方法指针。
这不是 魔法。
答案 3 :(得分:1)
当您创建匿名方法(例如分配给Func<T>
的方法)时,其中使用的本地人员将被提升到一个班级。考虑一下:
int GetIncremented()
{
int x = 0;
Func<int> increment = () => ++x;
increment();
return x;
}
在幕后,将会创建类似的内容:
sealed class FuncData
{
public int x = 0;
public int FuncIncrement(FuncData data)
{
return ++data.x;
}
}
int GetIncremented()
{
FuncData data = new FuncData();
Func<int> increment = new Func<int>(data.FuncIncrement);
increment();
return data.x;
}
这就是为什么out
和ref
参数不能与匿名方法一起使用的原因:您不能将out
或ref
存储为成员变量类。
答案 4 :(得分:1)
您同时拥有Func
和Action
,这些都是内置代理。它们之间的区别在于Func
返回一种类型而Action
没有。
您会发现Func
使用Linq扩展方法在IEnumerable(T) Interface
中大量使用。
从提供的MSDN链接看一下这个例子......
Func<string, string> selector = str => str.ToUpper();
string[] words = { "orange", "apple", "Article", "elephant" };
IEnumerable<String> aWords = words.Select(selector);
foreach (String word in aWords)
Console.WriteLine(word);
这主要使用 Selector Func 将单词中的每个字符串转换为大写。