Вопрос

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 -- 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.

Другие советы

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 marked specialname and rtspecialname, see §10.5.1) shall take exactly two parameters, the first having type System.Object, and the second having type System.IntPtr. When actually called (via a newobj 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top