✅ Using `Func<ReadOnlySpan<char>,bool>` but not allowed due to Pointer Type
I am building a parser, and performance is of concern. So instead of allocating infinite strings whenever I need to take a substring. I'd logically prefer to just take slices of the same buffer using Spans. In addition I want to use
Func<ReadOnlySpan<char>,bool>
to do some work in helping me parse, which would take in the Span to do some work. However, this is illegal in C# Compiler Error CS0306
due to ReadOnlySpan<char>
being a pointer type readonly ref struct
. I have considered just making a type, with one function on it, and overriding that in subtypes to get around it, but this is really not suitable. I may for instance wish to compile LINQ expressions at run time, to server as parsers.
This has got me stuck since the 'correct' way is illegal, and any other way, is highly comprimised. Thoughts?8 Replies
Can you just define your own delegate type?
public delegate bool MyDelegate(ReadOnlySpan<char> input);
or so?Hmm looks like it works
The problem is with
ref struct
types being used as generic type parameters. The compiler has rules around what it can and can't do with ref structs
, but if all it sees is a generic T
, it can't know what special rules apply when T
is a ref struct
(and Func
is, of course, a generic type)Yes this works completly, I thought for some reason whatever lambda used to define this, would also complain, but it works perfectly.
I have never needed to use delegates before (except when interfacing with older style code) so it's interesting to me that they still have uses and aren't fully superceded by Func and Action
Yeah, anything with
ref
/ out
needs a custom delegate type as well. And quite often it's just clearer, as you get to name your parameters, rather than having a fairly horrible Func<string, string, bool, bool, bool>
etc
(Func<T>
is, after all, just a convenience delegate T Func<T>()
defined in the BCL)
https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Function.csThanks @canton7 this solves everything, and delegate is mucher nicer here (even if it wasn't required, which it is).
I may start using my own delegates elsewhere, since it's good for when something isn't just a throw-away type for a random odd job (like value tuples vs record) I guess
Yeah, the downside is that all of linq uses Action/Func, and converting between delegate types is a little bit cumbersome
Plus
var foo = (int x) => { }
is automatically inferred as Action<int>
these days. So Action/Func are still a little bit special
But, the upsides of being able to name/document your parameters often outweigh that
$closeUse the /close command to mark a forum thread as answered