【问题标题】:F# discriminated unions versus C# class hierarchiesF# 可区分联合与 C# 类层次结构
【发布时间】:2011-11-12 03:18:25
【问题描述】:

我有以下代码:

public abstract class A ...
public class B : A ...
public class C : A ...

void my_fct(A x) {
  if (x is B) { block_1 }
  else if (x is C) { block_2 }
  else { block_3 }
}

我想知道它是否是来自 F# 的好翻译

type a = B | C
let my_fct x =
  match x with
  | B -> ( block_1 )
  | C -> ( block_2 )
  | _ -> ( block_3 )

??

【问题讨论】:

  • 我想没关系。除了你不见了;在block_1、block_2和block_3之后
  • 请原谅我的无知,但似乎block_3 永远无法在 F# sn-p 中执行(据我所知,代数数据类型是“封闭的”),所以为什么会出现?另外,我是唯一一个认为翻译应该使用多态性的人吗?
  • 关于 block_3,你们完全正确。
  • F# 模式匹配编译为程序集的跳转,因此联合案例的数量为 O(1)。为了在 C# 中匹配性能,您应该有一个 int 或 enum 编码案例编号,并将模式匹配编码为 switch 语句。

标签: c# f# class-hierarchy c#-to-f# discriminated-union


【解决方案1】:

F# 可区分联合与 OO 类层次结构非常接近,因此这可能是最佳选择。最显着的区别是您不能在不修改类型声明的情况下将新案例添加到有区别的联合中。另一方面,您可以轻松添加适用于该类型的新函数(这大致对应于在 C# 中添加新的虚拟方法)。

因此,如果您不希望添加新的继承类(案例),那么这是最佳选择。否则,您可以使用 F# 对象类型(或其他选项,具体取决于场景)。

关于您的代码还有一点 - 由于您无法添加新案例,F# 编译器知道您需要的唯一案例是 BC。结果,block_3 永远无法执行,这意味着您可以只写:

let my_fct x = 
  match x with 
  | B -> ( block_1 ) 
  | C -> ( block_2 ) 

【讨论】:

    【解决方案2】:

    是的,这或多或少与 F# 相同。 在这种情况下(没有添加值) - F# 似乎将其转换为“a”和一些标签(枚举)的类。 “a”类只有一些 B 和 C 的静态属性,以及一些检查“a”类型对象是“B”还是“C”的方法(见下文)

    但是你不需要 "_ -> (block_3)" 的情况,因为这永远无法匹配(F# 知道所有可能的情况并会警告你)。

    我认为最好在 C# 中为这种“其他”情况抛出异常。

    【讨论】:

    • 好吧,我猜托马斯说得更好;)
    猜你喜欢
    • 2011-12-29
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多