Method References

Function pointers

Function pointer types can point to static methods, external functions, or functions dynamically generated by libraries.

Delegates

Delegates are more general, and are defined as class types which can not only refer to anything a function can, but can also refer to instance methods and can hold local variable captures when they point to local methods or lambdas.

Lambdas

Lambdas are a shorthand for creating a local method and then allocating a delegate to point to it, except a lambda also allows you to define a lambda destructor for freeing any resources required during the lifetime of the lambda.

static void Test(StringView str)
{
    int i = 0;

    /* Locally defined method which captures 'i' by reference */
    char8 GetNext()
    {
        if (i >= str.Length)
            return 0;
        return str[i++];
    }

    /* Locally defined method with no captures */
    char8 GetEmpty()
    {
        return 0;
    }

    /* Allocates a delegate bound to GetNext() */
    delegate char8() strDlg = scope => GetNext;

    /* Bind emptyFunc to GetEmpty(). Binding to GetNext() would fail because function pointers cannot hold captures */  
    function char8() emptyFunc = => GetEmpty;

    strDlg = scope () =>
    {
        return 'A';
    };

    strDlg = scope [&] () =>
    {
        return GetNext();
    };

    /* This delegate owns a string */
    String tempStr = new String(str);
    tempStr.EnsureNullTerminated();
    strDlg = scope [&] () =>
    {
        return str[i++];
    }
    ~
    {
        delete tempStr;
    };
}

Valueless Method References

Valueless method references can be used to specialize certain types of generic methods such that they directly call the referenced method rather than calling indirectly through a delegate. This can improve performance in some types of critical code paths.

static T Max<T, TFunc>(T lhs, T rhs, TFunc func) where TFunc : delegate int(T lhs, T rhs)
{
    return (func(lhs, rhs) >= 0) ? lhs : rhs;
}

int CmpVec(Vector2 lhs, Vector2 rhs)
{
    return lhs.x <=> rhs.x;
}

/* The 'func' argument of this call is valueless - a specialized 'Max' method will be generated that directly calls CmpVec */
Vector2 max = Max(vec0, vec1, => CmpVec);