How to define a ref struct in F# in .NET Standard 2.0?

595 views Asked by At

When F# 4.5 was announced, it was stated that:

The F# feature set is comprised of

  • [...]

  • The ability to produce IsByRefLike structs (examples of such structs: Span<'T>and ReadOnlySpan<'T>).

How to "produce" these types? I tried the [<IsByRefLike>] attribute but is was not found in .NET Standard 2.0.

3

There are 3 answers

0
Theodore Tsirpanis On BEST ANSWER

Starting with .NET SDK 6.0.200 (available in Visual Studio 2022 17.1), the F# compiler recognizes user-defined IsByRefLikeAttributes. The following code will transparently enable defining ref structs on .NET Standard 2.0 as well as later frameworks:

#if NETSTANDARD2_0
namespace System.Runtime.CompilerServices

open System

[<Sealed; AttributeUsage(AttributeTargets.Struct)>]
type IsByrefLikeAttribute() = inherit Attribute()
#endif

namespace MyLibrary

open System
open System.Runtime.CompilerServices

[<IsByRefLike>]
type MyRefStruct(span: Span<int>) = struct end
2
nilekirk On

The attribute is found in System.Runtime.CompilerServices

open System.Runtime.CompilerServices

[<Struct; IsByRefLike>]
type Apa =
    { A: Span<int>
      B: int }

Phillip Carter talks about this in What's new in F# 4.5 (about 21 min. in).

It is available for .NET Core and .NET Framework, but not .NET Standard 2.0.

2
Konstantin Konstantinov On

Technically, this is not an answer.

First, according to the specs, IsByRefLike is for the compiler, not for the developers to use: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.isbyreflikeattribute?view=netframework-4.7.2

Second, when we do want something from a compiler, then it is crucial that we do understand what we want from it. So a correct question could be: I need ABC because I need to do XYZ, where ABC would be something related to IsByRefLike and then XYZ would be something based on IsByRefLike. The question does not explain why IsByRefLike is needed.

I think that a minimalist approach should be always weighted in when considering which language features to use / not to use: do we really need some particular language feature to accomplish what we need? F# Option.bind comes to mind: if the function is a one-liner then Option.bind is great. However, if there is some tree of how to parse the result, then it might be better to do that explicitly without using Option.bind.

So the questions are:

  1. Do you really need IsByRefLike?
  2. If you think that you do, could you, please, post an example of where you actually do need it.