跨 F#/C# 边界保留字段名称

2023-12-19

作为学习练习,我正在使用 F# 和 F# 的类型提供程序功能对 5000 行 csv 文件进行一些数据分析。当我在 f# 中使用类型提供程序生成的类型时,csv 文件的标题行自然会成为该类型的字段名称。

type restaurantCsv = CsvProvider<"C:\Users\Paul\Desktop\HealthDepartment\RestaurantRatings2013.csv",HasHeaders=true>

type RawInspectionData(filename : string) = 
    member this.allData = restaurantCsv.Load(filename)

    member public this.inspectionsList = this.allData.Data.ToList()

    member this.FilterByName(name : string) =
        this.allData.Data 
            |> Seq.filter (fun x -> x.EstablishmentName.Contains(name))

另外,我从单元测试 C# 文件调用 F# 代码(在上述代码创建的库中)。效果很好。但是,当我使用 F# 从 FilterByName 返回的 IEnumberable 时,不会保留字段名称信息。所以我有代码将新字段名称从元组映射到 .Item1、Item2 等:

var inspectionsOnCafes = inspections2013.FilterByName("Cafe");
var inspections = (from row in inspectionsOnCafes
                    select new
                    {
                       inspectorID = row.Item3,
                       restaurantName = row.Item5,
                       inspectionDate = row.Rest.Item6
                    }).ToList();

我的问题有没有办法让 C# 识别 F# 生成类型中的字段名称,这样我就不必将 row.Item# 映射到易于阅读的字段名称?换句话说,有没有办法可以得到这样的代码:

inspectorID = row.InspectorID,
// etc.

注:我看了如何创建可从 C# 使用的 F# 类型提供程序? https://stackoverflow.com/questions/12118866/how-do-i-create-an-f-type-provider-that-can-be-used-from-c但在我看来,Cameron Taggert 的问题和 Tomas Petricek 的答案在类型提供者的方面略有不同。即使他们是准确的,我也不明白,所以我仍然需要更多的帮助。


在 F# 中,有两种不同类型的类型提供程序。更常见和更简单的是擦除类型提供程序。更复杂的是生成类型提供者。

这种区别对于 C# 非常重要,因为:

  • 擦除的类型提供程序只是编译器的魔法。这是一种确保您的代码格式正确、正确使用底层 API 的方法。但这只是编译时的没有生成任何类型。相反,底层类型被用作内部表示。这种类型提供程序在 C# 中使用起来不太方便,因为在 C# 中您只能获取底层类型。

  • 生成类型提供程序是编译时真正的代码生成步骤。在这种情况下类型已生成因此实际上存在于程序集中并且可以从 C# 使用。

您所描述的问题正是人们所期望的erased类型提供商。而底层类型只是一个元组,但不会生成像类或记录这样的好类型。并且不能在 C# 中使用 F# 名称,除非类型提供程序的编写方式与生成类型提供程序不同。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

跨 F#/C# 边界保留字段名称 的相关文章

随机推荐