How does func ACTUALLY work
Asked Answered
W

5

5

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

Wilberwilberforce answered 12/12, 2013 at 20:13 Comment(4)
Are you asking what happens when you return from a method? Or what happens when you create an anonymous method (like one you'd assign to Func<T>)?Haroldharolda
Can you clarify, I'm not exactly sure if you are wondering how c# passes around objects (since you are talking about pointer passing) or if you are wondering about how closures work with delegate typesLuba
Possible duplicate of #12809173Metamorphism
@CoryNelson Sorry, I was implying when you return a func from a methodWilberwilberforce
P
6

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.

Pernambuco answered 12/12, 2013 at 20:18 Comment(4)
So it also includes instance information as well? For example what if there were instance variables that you needed to reference in the func that was passedWilberwilberforce
@AMR: Are you referring to variables captured by closure?Pernambuco
@AMR: In such cases the compiler generates a nested class and makes both the code and the variables you are capturing members of that class. The delegate then references the method and an instance of the class as it always does (think "MethodInfo + pointer to instance). The important thing to take home is that what the compiler does to allow you this convenience is unrelated to how Func works. If you wanted you could simulate the closure yourself (but of course noone does because that would be masochistic).Pernambuco
you get the prize. Thanks for indulging my curiosityWilberwilberforce
H
5

A Func is a delegate, and Delegate instances encapsulate a MethodInfo and an optional target object to invoke the method on when invoked.

Heribertoheringer answered 12/12, 2013 at 20:17 Comment(0)
D
3

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.

Daff answered 12/12, 2013 at 20:27 Comment(1)
@AMR, see my amended answer for the specifics.Daff
H
1

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.

Haroldharolda answered 12/12, 2013 at 20:25 Comment(1)
To the person who downvoted: how can I improve this answer? From AMR's reply to Jon, it provides exactly what he was looking for.Haroldharolda
I
1

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.

Imp answered 12/12, 2013 at 20:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.