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#
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. 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#).
So, if you don't expect to add new inherited classes (cases), then this is the best option. Otherwise, you may use F# object types (or other options, depending on the scenario).
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
. As a result, the block_3
can never be executed, which means that you can write just:
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. In this case (no values added) - F# seems to translate this into a classs for "a" and some Tags (enumeration). 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)
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).
I think it's better if you throw an exception in C# for this "else" case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With