【问题标题】:Properly implement F# Unit in C#在 C# 中正确实现 F# Unit
【发布时间】:2015-08-31 19:54:52
【问题描述】:

这个问题与this one 中的 C#/F# 兼容性无关。

我想知道实现F# Unit 之类的类型而不是使用void 的正确方法。

显然我会丢弃这个结果,我不会把这个类型暴露给外界。

想知道一个空类是否可以扮演这个角色。

internal class Unit
{
}

例如在language-ext库中,作者使用了struct

这个选择有什么好处吗?

【问题讨论】:

  • 结构体值和始终为空的类值在性能方面大致相同,但前者可以限制为奇异值,而后者则不能(null 和非null)。 internal abstract class Unit 会是一个更好的主意...
  • @Foole Dude,把你的评论放在答案框中,太棒了! :-)
  • @gsscoder :重点是允许奇异值。对于值类型,这很容易,因为它们不能为空;如果装箱,则值的类型为System.Object,而不是值类型。引用类型比较棘手,因为 null 总是一个可能的值;在这种情况下,null 是理想的标记值,目标是使 non-null 值成为不可能,因此在类上推荐abstractstatic。跨度>
  • @gsscoder 无需羞耻!不过,出于迂腐精确的考虑,我将指出值为 null 的 Nullable 与 null 引用不同。 (然而,这样的类型也不能满足 Thomas Petricek 的要求,即该类型只有一个值。)

标签: c# f# functional-programming unit-type


【解决方案1】:

我使用了这个 Unit 类型作为参考: https://github.com/louthy/language-ext/blob/main/LanguageExt.Core/DataTypes/Unit/Unit.cs

来自功能扩展库。

【讨论】:

【解决方案2】:

System.ValueTuple(没有泛型参数)在 C# 中非常unitThe source code 已打开。

【讨论】:

    【解决方案3】:

    我不确定在 C# 中定义 Unit 的最佳方式是什么。这可能与在 F# 中的实现方式不同(因为在 F# 中,编译器以某种方式隐藏了用法)。

    不过,你其实可以在核心库中找到F#unit的实现:

    这里是关于 F# unit 实现的关键点

    • 它以与 Rx 版本相同的方式实现 GetHashCodeEquals
    • IComparableunit 类型的所有值都相等
    • 最重要的是,它有一个私有构造函数,所以你不能创建一个新的unit 值。它也没有 默认实例(与 Rx 单位不同),因此在 F# 中,所有单位值实际上都表示为 null。但是,语言/编译器通常会隐藏这一事实。

    所以,听起来 F# 的唯一区别是它使用了 null 值。如果您想明确使用unit,这可能不是最佳选择。但是,如果您有 Unit.Default,那么您最终会定义一个具有两个可能值的类型,因为它可以是 Unit.Defaultnull(因此它并不是一个真正的单元!)

    【讨论】:

    • +1 这个回答我的问题和@Tomas Petricek 的观点让事情变得更清楚了。我还赞赏指向 F# 源的链接:有趣且有用。我还有最后一件事要问:在最后一句中,您说值可以是Unit.Defaultnull;但是如果我将类型定义为(如在 Rx 中)struct,如果没有明确装箱,它就不能是null。正确的?无论如何,一旦定义(例如:在可重用库中),我不会将其公开给 Public API;我计划(例如)定义Func<T...,Unit> 而不是Action<T...> (当绝对强制且副作用无法避免时)。
    • @gsscoder : "但如果我将类型定义为(如在 Rx 中)struct,如果没有明确装箱,它就不能是null。对吧? " 呃,如果一个值类型的对象被装箱,那么它将是运行时类型obj 并且它不会为空——值类型不能为空,句号(因此存在System.Nullable<> 有点模拟这)。无论如何,他只是在评论为什么 F# 没有可访问的构造函数或类似 Unit.Default 的任何东西(因为 F# 使用结构)。
    • @ildjarn 不,当一个结构被装箱时,它具有相关结构的 runtime 类型。也就是说,装箱的 int 具有 System.Int32 的运行时类型。持有对装箱实例的引用的 变量 可能具有对象、System.ValueType、System.Enum 的 静态 类型(即编译时类型),如果适当的,或结构实现的任何接口。当然,这样的变量可以有一个空引用。
    • Unit.Default 不一定意味着具有两个可能值的类型;它可以返回一个空引用。
    • @phoog :我的术语很糟糕,抱歉。
    猜你喜欢
    • 2012-12-05
    • 1970-01-01
    • 2021-01-26
    • 2023-03-25
    • 2018-07-29
    • 2020-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多