2010-12-12 23 views
40

Cosa membro dovrei implementare nella mia struttura arbitraria per rendere possibile la seguente assegnazione:Come inizializzare la struttura?

public struct MyStruct { 
    String s; 
    Int length; 
} 

MyStruct myStruct = new MyStruct { s = "Hello", length = 5 }; 

// Now, I want the following code to set the 's' to "Lol" and the 
// length to 3 (length of "Lol"). The second part should be done 
// automatically. 
myStruct = "Lol"; // Or myStruct = String("Lol"); 

Come si dovrebbe fare?

+4

Si prega di non creare strutture mutevoli. http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil – Ani

+0

'String già conoscono la loro lunghezza. Perché avresti bisogno di una struttura come questa? –

+0

@Karl Knechtel: presumo che sia un esempio per mostrare il principio. Il codice mostrato non viene nemmeno compilato ... – Guffa

risposta

72

Si utilizza un operatore implicito che converte il valore stringa in un valore struct:

public struct MyStruct { 
    public string s; 
    public int length; 

    public static implicit operator MyStruct(string value) { 
    return new MyStruct() { s = value, length = value.Length }; 
    } 

} 

Esempio:

MyStruct myStruct = "Lol"; 
Console.WriteLine(myStruct.s); 
Console.WriteLine(myStruct.length); 

uscita:

Lol 
3 
+0

il problema che posso vedere qui è una desvirtualizzazione della struct ... quando si usa l'operatore 'new' per restituire la struct, questo operatore metterà i dati nell'heap ... quindi forse è meglio usare questo codice come classe statica (quindi c'è una desincronizzazione del codice per il programmatore) ... e le cose ottengono coerenza ... – ZEE

+0

@ZEE: L'operatore 'new' non fa caso all'allocazione dell'heap per una struttura. In realtà non esiste alcun costruttore parametrico da chiamare, è solo la sintassi C# per creare un valore struct. – Guffa

0

tua struct può avere metodi e proprietà ... perché non provare

public struct MyStruct { 
    public string s; 
    public int length { return s.Length; } 
} 

Correzione @ risposta di Guffa dimostra che è possibile ... maggiori informazioni qui: http://www.codeproject.com/KB/cs/Csharp_implicit_operator.aspx

+0

Sì, è possibile. – Guffa

+0

@Guffa: risposta interessante ... Non ho considerato l'operatore implicito. –

4
  1. Will "lunghezza" mai deviare dalla lunghezza reale di "s". Se la risposta è no, non è necessario archiviare la lunghezza, perché le stringhe ne memorizzano già la lunghezza e puoi chiamare s.Length.

  2. Per ottenere la sintassi che hai chiesto, è possibile implementare un operatore "implicito" in questo modo:

    static implicit operator MyStruct(string s) { 
        return new MyStruct(...); 
    } 
    
  3. L'operatore implicita funzionerà, indipendentemente dal fatto che si effettua la struct mutabile o meno.

7

tipi struttura dovrebbe, quando praticabile, né hanno tutti del loro stato incapsulato in settori comuni che possono indipendentemente essere impostati tutti i valori che sono validi per i rispettivi tipo, oppure si comportano come un unico valore unitario che può solo scommessa impostata tramite costruttore, fabbrica, metodo, oppure passando un'istanza della struct come parametro esplicito ref a uno dei suoi metodi pubblici. Contrariamente a quanto sostengono alcune persone, non c'è niente di sbagliato in una struttura con campi pubblici, se si suppone che rappresenti un insieme di valori che possono essere sensibilmente manipolati individualmente o fatti passare come un gruppo (ad esempio le coordinate di un punto). Storicamente, ci sono stati problemi con le strutture che avevano insediamenti di proprietà pubbliche, e il desiderio di evitare i campi pubblici (sottintendendo che i setter dovrebbero essere usati) ha portato alcune persone a suggerire che le strutture mutabili dovrebbero essere evitate del tutto, ma i campi non hanno il problemi che avevano le proprietà. In effetti, una struttura a campo scoperto è la rappresentazione ideale per una raccolta libera di variabili indipendenti, dal momento che lo è solo una serie di variabili.

Nel tuo particolare esempio, tuttavia, sembra che i due campi della struttura non siano probabilmente indipendenti. Ci sono tre modi la tua struct potrebbe ragionevolmente essere progettato:

  • si potrebbe avere l'unico campo pubblico sia la corda, e poi hanno un sola lettura "aiutante" proprietà chiamata length che segnalare la lunghezza se la stringa non è nulla, o restituisce zero se la stringa è nulla.

  • È possibile che la struttura non esponga campi pubblici, setter di proprietà o metodi di mutazione e che il contenuto del solo campo, una stringa privata, sia specificato nel costruttore dell'oggetto. Come sopra, length sarebbe una proprietà che segnalerebbe la lunghezza della stringa memorizzata.

  • Si potrebbe avere la struttura non esporre campi pubblici, setter di proprietà o metodi di muting e avere due campi privati: uno per la stringa e uno per la lunghezza, entrambi impostati in un costruttore che accetta una stringa, la memorizza, ne misura la lunghezza e la memorizza. Determinare la lunghezza di una stringa è sufficientemente veloce che probabilmente non sarebbe utile calcolarlo e memorizzarlo nella cache, ma potrebbe essere utile avere una struttura che combina una stringa e il suo valore GetHashCode.

È importante essere a conoscenza di un dettaglio per quanto riguarda il terzo motivo, però: se il codice non threadsafe provoca un'istanza della struttura da leggere mentre un altro thread scrive ad esso, che può causare la creazione accidentale di un'istanza struct i cui valori di campo sono incoerenti. I comportamenti risultanti potrebbero essere leggermente diversi da quelli che si verificano quando le classi vengono utilizzate in modalità non a prova di bug. Qualsiasi codice che abbia a che fare con la sicurezza deve fare attenzione a non presupporre che i campi della struttura si trovino in uno stato coerente, dal momento che il codice malevolo - anche in un ambiente di "fiducia totale" - può facilmente generare strutture il cui stato è incoerente se è ciò che vuole fare.

PS - Se si desidera consentire la vostra struttura per essere inizializzati con un incarico da una stringa, vi suggerirei di usare un operatore di conversione implicita e facendo Length essere una proprietà di sola lettura che restituisce la lunghezza del sottostante stringa se non-null o zero se la stringa è nulla.

+1

Anche se fai alcuni punti interessanti, questo in realtà non risponde alla domanda. –

+0

Non ho notato l'ultimo incarico - solo il primo. Per consentire quest'ultimo, è possibile definire un operatore di conversione implicito da 'String' al tipo di struttura. Se lo fai, potresti desiderare che 'Length' sia una proprietà di sola lettura che riporta semplicemente la lunghezza del campo di stringa assegnato, o zero se quel campo è' null'. – supercat

+0

Dovresti includerlo nella risposta. Questo lo trasformerebbe in una risposta reale. E una volta che lo modifichi, potrò ritirare il mio downvote. –

Problemi correlati