Tendo a suddividere i miei campi in due categorie: i campi che vengono inizializzati immediatamente (ovvero tramite un costruttore, o un metodo di inizializzazione che si prevede venga chiamato prima di altre operazioni) e campi che possono essere impostati in qualsiasi momento.
Non seguo alcuna regola concreta, ma penso di tendere a seguire questo ordine:
1: Campi che vengono inizializzati immediatamente
2: Costruttori, in particolare quelli che inizializzano i campi da # 1
3: Metodi di inizializzazione che inizializzeranno i campi da # 1
4: ottieni / imposta metodi per i campi da # 1, se applicabile.
5: Altri campi che possono essere impostati in qualsiasi momento, insieme ai metodi get / set associati.
6: Metodi che utilizzano i campi.
Di seguito è riportato un codice di esempio che dimostra questo:
class Example1
{
// First: Fields with no associated properties,
// fields with read-only properties,
// or fields that will be initialized up front (i.e. in a constructor or an initialization method)
private int _Field1;
private string _Field2;
// Second: Constructors
public Example1(int field1, string field2)
{
_Field1 = field1;
_Field2 = field2;
}
public Example1() : this(0, null) { }
// Third: Methods that initialize fields
public void InitializeWithExampleData(ExampleDataObject data)
{
_Field1 = data.Value1;
_Field2 = data.Value2;
}
// Fourth: Properties for all fields that were previously declared
public int Field1
{
get { return _Field1; }
}
public string Field2
{
get { return _Field2; }
}
// Fifth: Other Fields along with read/write properties
// i.e. fields that are not initialized by any constructors or methods declared above
private int _Field3;
public int Field3
{
get { return _Field3; }
set { _Field3 = value; }
}
private string _Field4;
public string Field4
{
get { return _Field4; }
set { _Field4 = value; }
}
// Sixth: Methods that utilize fields
public int CalculateSomethingBasedOnFieldValues()
{
return this.Field1 + this.Field2.Length + this.Field3;
}
}
struct Example2 // Immutable type example
{
// First: Fields
private int _Field1;
private string _Field2;
// Second: Constructors (i.e. things that can write to the fields)
public Example2(int field1, string field2)
{
_Field1 = field1;
_Field2 = field2;
}
public Example2(int field1)
{
_Field1 = field1;
_Field2 = null;
}
// Third: Properties (i.e. things that can read from the fields)
public int Field1
{
get { return _Field1; }
}
public string Field2
{
get { return _Field2; }
}
}
Come ho detto, sono flessibile, ma tendo a farlo perché penso che l'ordine delle dichiarazioni tenda a seguire l'ordine delle operazioni che coinvolgono i campi, e questo mi rende felice dentro.
Innanzitutto, i campi sono dichiarati (ad esempio, la memoria è assegnata a loro). In secondo luogo, sono impostati, tramite un costruttore o un metodo di inizializzazione. In terzo luogo, vengono letti o utilizzati da altri metodi per eseguire un'operazione.
I campi che hanno sia un metodo get sia un metodo set non seguono chiaramente questo flusso, poiché potrebbero essere impostati in qualsiasi momento da un consumatore che chiama il metodo set, motivo per cui tendo a separarli in un'area diversa.