In .NET, un tipo di valore (C # struct
) non può avere un costruttore senza parametri. Secondo questo post, ciò è richiesto dalla specifica CLI. Quello che succede è che per ogni tipo di valore viene creato un costruttore predefinito (dal compilatore?) Che inizializza tutti i membri a zero (o null
).
Perché non è consentito definire un tale costruttore predefinito?
Un uso banale è per i numeri razionali:
public struct Rational {
private long numerator;
private long denominator;
public Rational(long num, long denom)
{ /* Todo: Find GCD etc. */ }
public Rational(long num)
{
numerator = num;
denominator = 1;
}
public Rational() // This is not allowed
{
numerator = 0;
denominator = 1;
}
}
Usando la versione corrente di C #, un Rational predefinito è 0/0
che non è così bello.
PS : I parametri predefiniti aiuteranno a risolverlo per C # 4.0 o verrà chiamato il costruttore predefinito definito da CLR?
Jon Skeet rispose:
Per usare il tuo esempio, cosa vorresti succedere quando qualcuno ha fatto:
Rational[] fractions = new Rational[1000];
Dovrebbe correre attraverso il tuo costruttore 1000 volte?
Certo che dovrebbe, ecco perché ho scritto il costruttore predefinito in primo luogo. Il CLR dovrebbe usare il costruttore di azzeramento predefinito quando non è definito alcun costruttore predefinito esplicito; in questo modo paghi solo per quello che usi. Quindi, se voglio un contenitore di 1000 Rational
s non predefiniti (e voglio ottimizzare le 1000 costruzioni) userò List<Rational>
un array anziché un array.
Questo motivo, secondo me, non è abbastanza forte da impedire la definizione di un costruttore predefinito.
Rational()
invoca il ctor senza parametri anziché il Rational(long num=0, long denom=1)
.
new Rational()
invocherà il costruttore se esiste, tuttavia se non esiste, new Rational()
sarà equivalente a default(Rational)
. In ogni caso sei incoraggiato a usare la sintassi default(Rational)
quando vuoi il "valore zero" della tua struttura (che è un numero "cattivo" con il tuo progetto proposto di Rational
). Il valore predefinito per un tipo di valore T
è sempre default(T)
. Quindi new Rational[1000]
non invocherà mai i costruttori di struct.
denominator - 1
all'interno della struttura, in modo che il valore predefinito diventi 0/1
Then if I want a container of 1000 non-default Rationals (and want to optimize away the 1000 constructions) I will use a List<Rational> rather than an array.
Perché dovresti aspettarti che un array invochi un costruttore diverso in un Elenco per una struttura?