Discussion: Permit static lambda assignment to function pointers · dotnet/csharplang · Discussion #6746 (original) (raw)

Considering this spec

Removing the static modifier from a lambda in a valid program does not change the meaning of the program.`

I would find it useful to be able to directly assign a lambda to a function pointer without & or static, as long as no variables are captured.

My use case is, I have a library that supports old versions of Unity (C# 4), and I conditionally compile with newer C# language features for better performance.

A simplified example similar to what I'm doing:

internal delegate void ConvertDelegate(object asyncResult, ref T storage, int index);

internal Merger : IAsyncResult, IIndexedCallback { internal T _result; private ConvertDelegate _converter;

internal Merger(ConvertDelegate<T> converter)
{
    _converter = converter;
}

void IIndexedCallback.Callback(object asyncResult, int index)
{
    _result = _converter(asyncResult, ref _result, index);
}

T IAsyncResult<T>.Result { get { return _result; } }

}

public static AsyncResult<ValueTuple<T1, T2>> Merge<T1, T2>(AsyncResult result1, AsyncResult result2) { var merger = new Merger<ValueTuple<T1, T2>>((object asyncResult, ref ValueTuple<T1, T2> storage, int index) => { if (index == 0) { storage.Item1 = ((IAsyncResult) asyncResult).Result; } else { storage.Item2 = ((IAsyncResult) asyncResult).Result; } }); result1.AddIndexedListener(merger, 0); result2.AddIndexedListener(merger, 1); return new AsyncResult<ValueTuple<T1, T2>>(merger); }

...

public static AsyncResult<ValueTuple<T1, T2, T3, T4>> Merge<T1, T2, T3, T4>(AsyncResult result1, AsyncResult result2, AsyncResult result3, AsyncResult result4) { ... }

And it would be very convenient for me if I could just change the Merger implementation to this so that the lambda expressions wouldn't have to change to fit function pointers and reduce duplicate code:

#if CSHARP_12_OR_GREATER // Or whichever language version private delegate*<object, ref T, int, void> _converter;

internal Merger(delegate*<object, ref T, int, void> converter)
{
    _converter = converter;
}

#else private ConvertDelegate _converter;

internal Merger(ConvertDelegate<T> converter)
{
    _converter = converter;
}

#endif

I know my use case is super niche and this may be unlikely to happen, but I figured I should give my input here.