A Func
is a delegate -- a type of object that is associated with a specific method signature and is usually bound to a specific method with that signature. This might be either a static
or an instance method and it might be generic or not; in all cases, the delegate instance holds all the information required to call the method.
문제
So when I return an object, under the covers I think it's returning the memory address to that object (or an object containing the memory address) which you can reference and use.
But what is actually happening when you return a func?
How does your app know which instance of an object to use with that func?
My instinct tells me that an object instance reference is passed along with the func but is that what is actually happening?
I can't seem to find much on this topic.
Edit: To clarify, I am asking when a method returns a func
해결책
다른 팁
A Func
is a delegate, and Delegate
instances encapsulate a MethodInfo
and an optional target object to invoke the method on when invoked.
Func<T>
is just a delegate. If it is set to an instance method, then, it [magically] gets the correct this
value when invoked. If set to a static method, then there is no this
. And if it's set to a closure/lambda, the closure "captures" those variables in scope at the time of closure. lexical scope (with some caveats: things don't always work the way you think they might).
Edited to add:
From the C# standard, ISO 23270:2006 Information Technology — Programming Languages — C#, §8.10:
8.10 Delegates
Delegates enable scenarios that some other languages have addressed with function pointers. However, unlike function pointers, delegates are object-oriented and type-safe.
A delegate declaration defines a class that is derived from the class
System.Delegate
. A delegate instance encapsulates one or more methods, each of which is referred to as a callable entity. For instance methods, a callable entity consists of an instance and a method on that instance. For static methods, a callable entity consists of just a method. Given a delegate instance and an appropriate set of arguments, one can invoke all of that delegate instance’s methods with that set of arguments.
In more detail, the other standard, ISO 23271:2006 Information Technology — Common Language Infrastructure (CLI) Partitions I to VI says in §14.6:
The instance constructor (named
.ctor
and markedspecialname
andrtspecialname
, see §10.5.1) shall take exactly two parameters, the first having typeSystem.Object
, and the second having typeSystem.IntPtr
. When actually called (via anewobj
instruction, see Partition III), the first argument shall be an instance of the class (or one of its derived classes) that defines the target method, and the second argument shall be a method pointer to the method to be called.
It's not that magic.
When you create an anonymous method, such as one assigned to a Func<T>
, locals used inside of it are lifted into a class. Consider this:
int GetIncremented()
{
int x = 0;
Func<int> increment = () => ++x;
increment();
return x;
}
Behind the scenes, something like this will be created:
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;
}
This is why out
and ref
parameters can't be used with anonymous methods: you can't store an out
or ref
as a member variable in a class.
You have both Func
and Action
, which are in-built delegates. The difference between these is that Func
returns a type and Action
does not.
You'll find Func
uses heavily in the IEnumerable(T) Interface
, with Linq extension methods.
Take a look at this example from the MSDN link provided...
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);
This essentially uses the Selector Func to convert each of the strings in words to upper case.