Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Generic anonymous methods (and functional interfaces) #3577

Closed
IS4Code opened this issue Jun 17, 2020 · 2 comments
Closed

Proposal: Generic anonymous methods (and functional interfaces) #3577

IS4Code opened this issue Jun 17, 2020 · 2 comments

Comments

@IS4Code
Copy link

IS4Code commented Jun 17, 2020

Whilst writing a highly general and highly generic system primarily focused on value types and dynamic communication therebetween, I have come to a conclusion that the most performant way to obtain a value of any type is with a receiver interface:

public interface IValueReceiver
{
    void Receive<T>(T value) where T : struct;
}

void GetValue<TReceiver>(ref TReceiver receiver) where TReceiver : struct, IValueReceiver;

A simple implementation of one such a receiver (to prove you can do something useful with T) would look like this:

public struct CompareReceiver : IValueReceiver
{
    public int Result;

    void IValueReceiver.Receive<T>(T value)
    {
        Result = System.Collections.Generic.Comparer<T>.Default.Compare(value, default);
    }
}

However, this results in a code looking not unlike the situation in C# 1 where there were no anonymous methods – callbacks have to be moved aside the method's code.

I'd very much like to be able to write something like this instead:

int result = 0;
GetValue(delegate<T>(T value)
{
    result = System.Collections.Generic.Comparer<T>.Default.Compare(value, default);
});

Analogously to normal functions, anonymous functions could be written with generic parameters and, optionally, even constraints.

This necessitates having a specific kind of delegate type with a generic Invoke method such as this:

public delegate<T> ValueReceiver(T value) where T : struct;

Now this requires CLR support if ValueReceiver has to inherit from System.Delegate, but there is another option: functional interfaces.

Going back to the original IValueReceiver, perhaps no additional type is needed at all: the compiler could create an anonymous type implementing IValueReceiver, closing over result. It also seems real that, upon seeing ref and the struct constraint, it would create a value type (and it should prefer so even when there is only ref).

This notion of functional interfaces could be extended to all cases, even non-generic ones. Such an interface must have no other methods than Invoke, BeginInvoke, EndInvoke, and DynamicInvoke (with the usual parameters), and thus in the end, the compiler would be able to convert any anonymous method or lambda to both delegates and interfaces that have these methods.

This is also similar to #3050 with its set of target problems and introducing new type parameters, but doesn't require reflection.

@quinmars
Copy link

Related: #2517 and #3452

@YairHalberstadt
Copy link
Contributor

Closing as duplicate of #2517 and #3452

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants