2011-09-07 17 views
6

tengo el siguiente código:F # sindicatos discriminados frente a C# clase jerarquías

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

y me pregunto si es una buena traducción de F #

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

??

+0

Supongo que está bien. Excepto que estás perdido; después de block_1, block_2 y block_3 –

+2

Disculpe mi ignorancia, pero parece que 'block_3' nunca se puede ejecutar en el fragmento F # (los tipos de datos algebraicos están" cerrados "hasta donde yo sé), entonces ¿por qué está ahí? Además, ¿soy el único que piensa que la traducción debería usar polimorfismo? – delnan

+0

Absolutamente todos tienen razón sobre block_3. – Hugo

Respuesta

11

Las uniones discriminadas F # corresponden a las jerarquías de clase OO bastante de cerca, por lo que esta es probablemente la mejor opción. La diferencia más notable es que no puede agregar nuevos casos a una unión discriminada sin modificar la declaración de tipo. Por otro lado, puede agregar fácilmente nuevas funciones que funcionen con el tipo (que corresponde aproximadamente a la adición de nuevos métodos virtuales en C#).

Por lo tanto, si no espera agregar nuevas clases heredadas (casos), esta es la mejor opción. De lo contrario, puede usar tipos de objetos F # (u otras opciones, dependiendo del escenario).

Un punto más con respecto a su código, ya que no puede agregar casos nuevos, el compilador de F # sabe que los únicos casos que necesita son B y C. Como resultado, la block_3 no se puede ejecutar, lo que significa que se puede escribir simplemente:

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

sí, esto es más o menos lo mismo que F # hace de todos modos. En este caso (sin valores agregados) - F # parece traducir esto en una clase para "a" y algunas etiquetas (enumeración). La clase de "a" sólo tiene algunas propiedades estáticas para B y C, y algunos métodos para comprobar si un objeto de tipo "a" es "B" o "C" (ver más abajo)

Object-Browser of the types

Pero no necesita el caso "_ -> (bloque_3)", porque esto nunca puede coincidir (F # conoce todos los casos posibles y le avisará).

Creo que es mejor si lanza una excepción en C# para este caso "else".

+0

bueno, supongo que Tomas lo dijo mejor;) – Carsten

Cuestiones relacionadas