2009-02-11 9 views
18

E 'possibile nascondere il costruttore senza parametri da un utente in C#nascondere senza parametri costruttore sul struct

Voglio costringerli utilizzare sempre il costruttore con i parametri

esempio questa classe posizione

public struct Position 
{ 
    private readonly int _xposn; 
    private readonly int _yposn; 

    public int Xposn 
    { 
     get { return _xposn; } 
    } 

    public int Yposn 
    { 
     get { return _yposn; } 
    } 

    public Position(int xposn, int yposn) 
    { 
     _xposn = xposn; 
     _yposn = yposn; 
    }   
} 

voglio solo che gli utenti siano in grado di nuovo una posizione specificando il coordinate x e y

Tuttavia, il costruttore senza parametri è SEMPRE availiable

non riesco a renderlo privato . O anche definirlo come pubblico

Ho letto questo Why can't I define a default constructor for a struct in .NET?

ma realmente non aiuterà

Se questo non è possibile - qual è il modo migliore per individuare se la posizione mi viene passato ha valori?

Controllare esplicitamente ogni campo proprietà? C'è un modo più semplice?

grazie

risposta

19

No, non puoi farlo. Come hai detto, è stato chiesto prima il numero similar question e ho pensato che la risposta fosse abbastanza chiara da non poterlo fare.

create a private parameterless constructor for a struct, ma non in C#. Tuttavia, anche se si fa che in realtà non aiuta - perché si può facilmente lavorare intorno ad esso:

MyStruct[] tmp = new MyStruct[1]; 
MyStruct gotcha = tmp[0]; 

che sarà il valore predefinito di MyStruct - il valore "tutti zeri" - senza mai chiamare un costruttore .

Si potrebbe facilmente aggiungere un metodo Validate alla propria struct e chiamare ogni volta che ne è stato ricevuto uno come parametro, ammettiamolo.

+3

Lo vedo come un problema di usabilità più di ogni altra cosa. Il costruttore predefinito potrebbe creare un oggetto _valid_, ma per molte strutture non sarà ciò che l'utente vorrebbe o si aspetterebbe. Tuttavia alcune persone useranno quel costruttore di default solo perché è la prima opzione che i loro IDE danno loro.E poi avranno confusi bug causati da strutture azzerate che dovrebbero essere state riempite di dati, o perderanno tempo a cercare di capire perché non possono impostare le proprietà su una struttura immutabile. Da una prospettiva di progettazione API vorrei che fosse possibile nascondere il costruttore predefinito. –

+1

+1 @ MB. Un costruttore privato predefinito sarebbe d'aiuto, anche se un determinato "pazzo" può aggirarlo. Come un sale in C++, penso a 'private' come un suggerimento per non spararti ai piedi, c'è sempre un work-around che usa i puntatori. E la semantica dell'array può essere gestita semplicemente non consentendo la creazione di array di tali strutture. –

+0

@roryapL Risolto, grazie. –

2

Beh una struct è letteralmente una dichiarazione di come la memoria siederà.

Anche quando si utilizza un oggetto, viene dichiarato il puntatore degli oggetti, indipendentemente dal fatto che sia null.

La ragione per cui non è possibile nascondere il costruttore è perché la struttura richiede che il CLR possa crearlo internamente e deve farlo.

È possibile convertire questa struttura in oggetto per ottenere questo compito. O usi l'analisi statica per assicurarti che sia intializzata prima di usarla?

struct point 
{ 
    int xpos; 
    int ypos; 
} 

Avere un google per gli oggetti immutabili, questo sembra essere ciò che il vostro dopo. Credo che stiano cercando di aggiungere questa funzionalità (ma non in C# 4) alla lingua stessa, perché è un requisito comune. C'è una necessità specifica per una struttura qui?

+0

cosa intendi con questo? usa l'analisi statica per assicurarti che sia intializzata vuoi dire che ogni campo ha un valore? – ChrisCa

+0

È possibile eseguire uno strumento di analisi statico con una regola per garantire che ogni volta che qualcuno utilizza il tipo nel proprio codice che i due valori siano inizializzati. oppure potresti fare un po 'di gioco di fantasia dichiarandolo come un oggetto per fare il controllo, e poi passare a una struttura nella build di rilascio. – Spence

4

Nope non può nasconderlo. Le strutture non possono ridefinire il costruttore di zero arg, quindi la sua visibilità non può essere ridefinita.

+0

Bene, .NET consente di fornire un costruttore parametrico personalizzato, ma non è possibile farlo * direttamente * in C# e non è di grande aiuto in quanto si può facilmente aggirarlo. –

1

Non è possibile creare una struct con un costruttore privato senza parametri o anche dichiarare un costruttore senza parametri. Dovresti cambiarlo in una classe. Le strutture non consentono di dichiarare un costruttore senza parametri.

Dal Structs Tutorial su MSDN:

Structs può dichiarare i costruttori, ma devono prendere i parametri. È un errore dichiarare un costruttore predefinito (senza parametri) per una struttura. I membri di Struct non possono avere inizializzatori. Viene sempre fornito un costruttore predefinito per inizializzare i membri della struct ai loro valori predefiniti.

Dal C# specification su MSDN:

11.3 Classe e struct differenze

Structs differiscono dalle classi in diversi modi importanti:

  • Structs sono tipi di valore (Sezione 11.3.1).
  • Tutti i tipi di struct ereditano implicitamente dalla classe System.ValueType (Sezione 11.3.2). L'assegnazione a una variabile di un tipo struct crea una copia del valore assegnato a (Sezione 11.3.3).
  • Il valore predefinito di una struttura è il valore prodotto modificando tutti valore campi di tipo al loro valore predefinito e tutti i campi di tipo riferimento a null (Sezione 11.3.4). Le operazioni di boxing e unboxing vengono utilizzate per convertire tra un tipo di struttura e l'oggetto (Sezione 11.3.5).
  • Il significato di questo è diverso per le strutture (Sezione 11.3.6).
  • Le dichiarazioni del campo di istanza per una struttura non possono includere gli inizializzatori variabili (Sezione 11.3.7).
  • Una struttura non è autorizzata a dichiarare un costruttore di istanze senza parametri (Sezione 11.3.8).
  • Una struttura non è autorizzata a dichiarare un distruttore (Sezione 11.3.9).