SRTP 成员限制看不到 C# 类的原始字段?

SRTP member constraits can't see raw fields of C# classes?

提问人:nodakai 提问时间:3/15/2023 更新时间:3/15/2023 访问量:77

问:

我对“类型”不支持运算符“”感到惊讶 错误如下:Lib1.Class1get_Id

F# 项目Lib0.fsproj

namespace Lib0

type T0 =
  val Id: string
  new s={Id=s}
type T1 =
  val mutable Id: string
  new s={Id=s}

C# 项目Lib1.csproj

namespace Lib1;
public class Class1
{
  public string Id;
  public Class1(string id) {
    Id = id;
  }
}

public class Class2
{
  public string Id { get; set; }

  public Class2(string id) {
    Id = id;
  }
}

F# 项目Test1.fsproj

module Lib =
  type T2 =
    val Id: string
    new s={Id=s}
  type T3 =
    val mutable Id: string
    new s={Id=s}

let inline f<'T when 'T: (member Id: string)> (x: 'T) = x.Id

f (Lib0.T0("Lib0.T0")) |> printfn "%s"  // ok
f (Lib0.T1("Lib0.T1")) |> printfn "%s"  // ok
f (Lib.T2("Lib.T2")) |> printfn "%s"  // ok
f (Lib.T3("Lib.T3")) |> printfn "%s"  // ok
// f (Lib1.Class1("Class1")) |> printfn "%s"  // The type 'Lib1.Class1' does not support the operator 'get_Id'
f (Lib1.Class2("Class2")) |> printfn "%s"  // ok


真??还是我错过了什么明显的东西??

澄清一下,我在这里做出的令人失望的观察是:

  1. F# 定义的类与 SRTP 成员约束兼容
  2. 具有属性的 C# 定义的类也兼容
  3. 带有原始字段的 C# 定义的类不兼容,这对我来说是新闻

如果 Rider 的 IL 查看器没有让我失望,至少应该公开它的原始字段,没有任何包装属性。那么 vs 和之间可能有什么区别呢?F# 定义的类是否具有额外的元数据(用于内联?),这些元数据在这里会有所不同?T1stringT1Lib1.Class1

(注意:使用 F# 7 之前的 SRTP 语法 () 似乎没有帮助。^T

背景:我需要处理一堆恰好具有公共字段(不是属性)的第三方 C# 类,例如 https://github.com/pulumi/pulumi-aws/blob/master/sdk/dotnet/S3/GetBucket.cs#L230public stringId

如果这是 SRTP 的真正限制,我想我必须在我的代码中到处插入一个包装器类型。这不会是世界末日,但会让代码变得混乱......

F# 鸭子 结构类型 adhoc-polymorphism

评论

3赞 Gus 3/15/2023
SRTP 不适用于字段。对于 F# 类型,总是有 getter,但这是 F# 的事情。get_..
0赞 nodakai 3/15/2023
嗯,所以当 F# 规范提到一个“成员”时,它是一个 F# 成员,它要么是属性,要么是方法,不像 C# 成员包含字段 learn.microsoft.com/en-us/dotnet/csharp/programming-guide/...,然后有一些特殊的“F# 东西”支持 F# 字段作为一个不错的功能(?)。这很可悲。也许我应该把它发布到?除非它显然毫无意义valfslang-suggstions

答: 暂无答案