简体   繁体   English

F#区分联合与C#类层次结构

[英]F# discriminated unions versus C# class hierarchies

I have the following code: 我有以下代码:

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 }
}

and I wonder if it is a good translation from F# 我想知道它是否是来自F#的良好翻译

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

?? ??

F# discriminated unions correspond to OO class hierarchies quite closely, so this is probably the best option. F#区分联合对应于OO类层次结构非常接近,因此这可能是最佳选择。 The most notable difference is that you cannot add new cases to a discriminated union without modifying the type declaration. 最显着的区别是,您无法在不修改类型声明的情况下将新案例添加到区分联合。 On the other hand, you can easily add new functions that work with the type (which roughly corresponds to adding new virtual methods in C#). 另一方面,您可以轻松添加使用该类型的新函数(大致对应于在C#中添加新的虚拟方法)。

So, if you don't expect to add new inherited classes (cases), then this is the best option. 因此,如果您不希望添加新的继承类(case),那么这是最佳选择。 Otherwise, you may use F# object types (or other options, depending on the scenario). 否则,您可以使用F#对象类型(或其他选项,具体取决于方案)。

One more point regarding your code - since you cannot add new cases, F# compiler knows that the only cases you need are for B and C . 关于您的代码还有一点 - 由于您无法添加新案例,F#编译器知道您需要的唯一案例是BC As a result, the block_3 can never be executed, which means that you can write just: 因此, block_3永远不会被执行,这意味着你可以只写:

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

yes this is more or less the same as F# does anyhow. 是的,无论如何,这或多或少与F#相同。 In this case (no values added) - F# seems to translate this into a classs for "a" and some Tags (enumeration). 在这种情况下(没有添加任何值) - F#似乎将其转换为“a”和一些标签(枚举)的类。 The class for "a" just has some static properties for B and C, and some methods to check if an object of type "a" is "B" or "C" (see below) “a”的类只有B和C的一些静态属性,以及一些检查“a”类型的对象是“B”还是“C”的方法(见下文)

对象浏览器的类型

But you don't need the "_ -> (block_3)" case, because this can never be matched (F# knows all the possible cases and will warn you). 但是你不需要“_ - >(block_3)”的情况,因为这永远不能匹配(F#知道所有可能的情况并会警告你)。

I think it's better if you throw an exception in C# for this "else" case. 我认为如果你在C#中为这个“其他”情况抛出异常会更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM