gpt4 book ai didi

c# - 使用属性来约束类型 - .NET

转载 作者:太空狗 更新时间:2023-10-30 01:17:21 25 4
gpt4 key购买 nike

在你离开之前:虽然我的代码是在 F# 中,但这个问题适用于任何 .NET 语言。

这是我的情况——我在 F# 中有一个简单的 ProgramOptions 记录,用于保存命令行选项数据。每个字段代表一个不同的选项,它们可以有默认值,这些默认值用自定义属性标记。

type ProgramOptionAttribute(defaultValue: obj) =
inherit Attribute()

type ProgramOptions =
{ [<ProgramOption("render.pdf")>] output: string
[<ProgramOption(true)>] printOutput: bool
// several more
}

我在别处写了一个不错的小函数,在给定原始命令行选项的情况下,使用属性数据动态实例化此记录。效果很好。但是通过向属性提供一个与字段不同类型的对象来引入运行时类型不匹配真的很容易(因为后面只有一个简单的从 obj -> 字段类型的转换)。例如:

// Obviously wrong, but compiles without complaint, failing at runtime
[<ProgramOption(42)>] myField: bool

有没有办法使该类型安全?某种通用的诡计?或者我想要的是不可能的?

最佳答案

据我所知,这是不可能的,但即使是这样,它对您有什么好处?您只能在属性中使用文字,因此您将被限制为 string , int , bool ,以及其他一些类型。

如果有一天,您想要用 DateTimeOffset 定义一条记录怎么办?它的值(value)(不是不合理的情况)?

type myRecord = {
[<ProgramOption(???)>]Date : DateTimeOffset
[<ProgramOption("foo")>]Text : string }

哪个ProgramOption你会穿上 Date 吗?元素?

也就是说,您不一定非得想出自己的属性。 BCL 已经定义了一个 [<DefaultValue>] attribute ,以及许多所谓的 data annotations attributes .在我看来,它们都没有用处。例如,here's an in-depth explanation of why the Required attribute is redundant .那篇文章是关于面向对象设计的,但也适用于函数式编程。

在像 F# 这样的静态类型函数式语言中,您应该 make illegal states unrepresentable .

最终,我认为一种更简单的方法是为每种类型定义一个默认值,如下所示:

type ProgramOptions = {
Output: string
PrintOutput: bool
// several more
}

let defaultProgramOptions = { Output = "render.pdf"; PrintOutput = true }

这将使您可以轻松地根据默认值创建值:

let myProgOps = { defaultProgramOptions with PrintOutput = false }

这是在编译时类型安全,并产生一个 ProgramOptions这些组成元素的值(value):

{ Output = "render.pdf"; PrintOutput = false; }

关于c# - 使用属性来约束类型 - .NET,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32105114/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com