2011-09-07 15 views
6

ho il seguente codice:F # sindacati discriminati rispetto a C# classe gerarchie

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

e mi chiedo se è una buona traduzione da F #

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

??

+0

Immagino sia tutto ok. Tranne che ti stai perdendo; dopo block_1, block_2 e block_3 –

+2

Scusa la mia ignoranza, ma sembra che 'block_3' non possa mai essere eseguito nello snippet F # (i tipi di dati algebrici sono" chiusi "per quanto ne so), quindi perché è lì? Inoltre, sono l'unico a pensare che la traduzione dovrebbe usare il polimorfismo? – delnan

+0

Hai assolutamente ragione su block_3. – Hugo

risposta

11

Le unioni discriminate F # corrispondono a gerarchie di classi OO abbastanza da vicino, quindi questa è probabilmente l'opzione migliore. La differenza più importante è che non è possibile aggiungere nuovi casi a un'unione discriminata senza modificare la dichiarazione del tipo. D'altra parte, puoi facilmente aggiungere nuove funzioni che funzionano con il tipo (che corrisponde approssimativamente all'aggiunta di nuovi metodi virtuali in C#).

Quindi, se non si prevede di aggiungere nuove classi ereditate (casi), questa è l'opzione migliore. Altrimenti, è possibile utilizzare i tipi di oggetto F # (o altre opzioni, a seconda dello scenario).

Un altro punto per quanto riguarda il codice: poiché non è possibile aggiungere nuovi casi, il compilatore F # sa che gli unici casi necessari sono per B e C. Di conseguenza, il block_3 non può mai essere eseguito, il che significa che è possibile scrivere semplicemente:

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

sì questo è più o meno lo stesso di F # fa comunque. In questo caso (nessun valore aggiunto) - F # sembra tradurre questo in classi per "a" e alcuni Tag (enumerazione). La classe di "a" deve solo alcune proprietà statiche per B e C, e alcuni metodi per verificare se un oggetto di tipo "a" è "B" o "C" (vedi sotto)

Object-Browser of the types

Ma non hai bisogno del caso "_ -> (block_3)", perché questo non può mai essere abbinato (F # conosce tutti i possibili casi e ti avviserà).

Penso che sia meglio se si lancia un'eccezione in C# per questo caso "altro".

+0

beh immagino che Tomas lo abbia messo meglio;) – Carsten