在 F# 中使用可空引用类型实现 C# 接口

Implementing C# interfaces with nullable reference types in F#

我正在尝试通过转换 C# 中的现有 .NET Core 解决方案来学习 F#,一次一个项目。我目前在 C# 中有一个具有可空引用类型的接口:

public interface IVehicle {
    public int GetWheels();
    public string? GetLicensePlate();
}

并且此接口在许多依赖于此的其他项目中实现。我正在尝试将其中之一转换过来,但如果我尝试

type Car(serialNumber: string) =
    interface MyProjectInterfaces.IVehicle with
        member this.GetWheels() = 4
        member this.GetLicensePlate() = 
            match LicensePlateService.GetLicencePlate(serialNumber) with
                | Some(x) -> System.Nullable(x)
                | None -> System.Nullable()

我收到错误:

This expression was expected to have type 'string' but here has type 'Nullable<string>'

这似乎不会影响值类型,所以我假设它与 string 作为引用类型有关。

我该怎么做才能解决这个问题?据推测,我可以重写底层接口以使用 F# 并因此使用选项,但还有其他 C# 项目实现了该接口,我不想一次性重写整个解决方案。还是我做的 F# 完全错了?

这是 C# 8 的可空引用和可空值类型之间的混淆,又名 Nullable<T>。如果您查看 Nullable<T> 的定义,您会发现:

public struct Nullable<T> where T : struct

这意味着它仅适用于值类型。 int?Nullable<int> 的缩写。 这与可为空的 references.

不同

The nullability modifier for reference types doesn’t introduce a new type. Reference types are still nullable and compiling string? results in IL that’s still just System.String.

The difference at the IL level is the decoration of nullable modified types with a NullableAttribute.

换句话说,它只是一个编译器构造 - 对 F# 不可见。

match LicensePlateService.GetLicencePlate(serialNumber) with
| Some(x) -> x
| None -> null

将是正确的,尽管不是惯用的替代。