2013-08-08 12 views
7

voglio scrivere l'equivalente di questo C# in F #:Come dichiarare una struttura immutabile con campi pubblici?

struct Vector2 { 
    public readonly int X; 
    public readonly int Y; 
    public Vector2(int x, int y) { 
     X = x; 
     Y = y; 
    } 
} 

Questo costringe l'utente a fornire argomenti di creare un'istanza [EDIT: questo è sbagliato per i tipi di valore - tutti i tipi di valore hanno un costruttore di default] . Un vettore predefinito può essere fornito anche con un campo statico di sola lettura, ad esempio Vector2.Zero.

Sembra che l'unico modo per ottenere campi pubblici è tramite la parola chiave "val", ma non sembra lasciarmi loro inizializzare con il costruttore di default, e io non voglio avere due costruttori:

[<Struct>] 
    type MyInt(value) = 
     val public Value : int = value;; 

      val public Value : int = value;; 
    -------------------------------^ 

stdin(7,32): error FS0010: Unexpected symbol '=' in member definition 

So che questo può essere fatto con associazioni membro, ma questo crea proprietà, non campi, se ho capito bene.

risposta

5

Secondo questa http://msdn.microsoft.com/en-us/library/vstudio/dd233233(v=vs.120).aspx, che potrebbe essere fatto come

type Vector2 = 
    struct 
     val public X: int 
     val public Y: int 
     new(x: int, y: int) = { X = x; Y = y } 
    end 
+0

Purtroppo questo mi consente di creare un vettore senza passare parametri, in questo modo: 'let v = Vector2()'. Non che questo sia un problema molto serio, ma mi sto ancora chiedendo se può essere fatto senza avere un costruttore vuoto predefinito. – Asik

+5

@Asik: lo stesso vale per il codice C#: questa è una limitazione CLR, non una limitazione F #. – ildjarn

+1

"Le strutture non possono avere un costruttore di oggetti senza argomenti: questa è una restrizione imposta su tutti i linguaggi della CLI poiché le strutture supportano automaticamente un costruttore predefinito." - questo è quello che dice il compilatore, quindi non è sempre possibile ottenere ciò che si desidera ... –

2

Se un F # Record avrebbe funzionato per voi, allora questo lavoro:

type MyInt = { 
    Value: int 
};; 

Poi, per inizializzare:

let i = {Value=1};; 

Dato che non sono completamente sicuro del vostro caso d'uso, non sono sicuro di quanto utile sia è.

EDIT: Per quel che vale, se la vostra ragione per preferire un tipo di valore è che si desidera tipo di valore la semantica di uguaglianza, dati di supporto che (anche se sono tipi di riferimento). Considerate questo:

type Vector2 = { 
    X:int; 
    Y:int 
};; 

type Vector2 = 
    {X: int; 
    Y: int;} 

let v = {X=1;Y=1};; 

val v : Vector2 = {X = 1; 
        Y = 1;} 

let v2 = {X=1;Y=1};; 

val v2 : Vector2 = {X = 1; 
        Y = 1;} 

v = v2;; 
val it : bool = true 

let v3 = {X=2;Y=2};; 
v = v3;; 
val it: bool = false 

Voglio dire che, anche se i record sono tipi di riferimento, uno dei motivi che le persone utilizzano i tipi di valore (la semantica di uguaglianza) non è un problema con i record. Anche se si tratta di un tipo di riferimento, credo che sia molto più vicino al comportamento del codice C# che stai cercando di emulare, per quello che vale.

+0

Il problema con i record è che sono implementati come tipi di riferimento con proprietà e qui sto cercando di ottenere un tipo di valore con i campi. – Asik

+0

Ancora: non conoscete il vostro caso d'uso, ma anche se i record sono tipi di riferimento, hanno semantica dell'uguaglianza di tipo value. Ho modificato la mia risposta per spiegarlo un po 'oltre. –

+0

Non ho davvero un caso d'uso, stavo solo cercando di capire come creare un tipo di valore con campi immutabili pubblici (nel senso di CLR) ed evitare di avere un costruttore predefinito. Grazie comunque per le tue spiegazioni. – Asik

Problemi correlati