This is a case in which one must use a delegate and cannot use Func or Action.
using System.Memory;
public delegate Span<byte> SpanFactoryFunc();
public Span<byte> CallSpanFactory(SpanFactoryFunc spanFactory)
{
return spanFactory();
}
There are other cases as well in which one must use a delegate because of limitations in generic type parameters. This question identifies one such situation -- where one wishes to pass as a parameter a method that includes a parameter being passed by reference. That cannot be accomplished with Func or Action, because there is no such thing as a ref generic type parameter. There is no syntax like Func<ref float, object>
.
The limitation on generic type parameters here is different: There is no syntax like Func<MyRefStruct>
or Func<MyRefStruct, object>
even without the "ref" modifier. This is NOT because MyRefStruct
will always be implicitly passed by reference. Ref structs are not always implicitly passed by reference. They can be passed either by reference or value. Similarly, ref structs are not always returned as "ref returns".
It follows that the form of the delegate matters -- the following two delegates will have different effects:
public ref struct MyRefStruct
{
// ...
}
public delegate void MyRefStructMutator(ref MyRefStruct s); // s is passed by reference
public delegate void MyRefStructAction(MyRefStruct s); // s is passed by value
Note that if instead of ref struct MyRefStruct
, we had a struct
or a class
called MyType
, there would have been no need for a delegate analogous to MyRefStructAction
; one could simply use Action<MyType>
. Similarly, one could use Func<MyType>
to return MyType. It is only with the advent of ref struct
s that using a delegate becomes necessary when passing a method that passes a parameter by value or returns by value.