3

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.

Community
  • 1
  • 1

3 Answers3

3

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.

Cinder Biscuits
  • 4,880
  • 31
  • 51
nilekirk
  • 2,353
  • 1
  • 8
  • 9
  • Thanks for the answer! I have tried it, but unfortunately, this attribute does not exist in .NET Core. I will change the wording of my question. – Theodore Tsirpanis Dec 28 '18 at 11:55
  • 1
    Indeed, it's not available in .NET Standard 2.0, only in .NET Core and .NET Framework. It is announced to be included in .NET Standard 2.1, though. – nilekirk Dec 28 '18 at 14:09
0

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
-3

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.
  • 1. No, my code can do without it. The data structure in question is not holding another ref struct. 2. I had thought about using it to enforce that the type stays on the stack, for safety and correctness reasons. – Theodore Tsirpanis Jan 04 '19 at 12:56
  • 1
    @TheodoreTsirpanis I think that where the data is located should the least of developer's concern unless it is explicitly needed due to some reason. I've given F# tasks to sort list of millions elements and it did just fine. So, I suggest that you forget about this attribute unless / until you really need it. – Konstantin Konstantinov Jan 04 '19 at 13:08