È possibile modificare il valore predefinito di un tipo di dati primitivo?
-
05-07-2019 - |
Domanda
Di recente ho creato una matrice generica < T > classe che funge da involucro attorno a una Lista < Lista < T > > collezione. Per quanto ne so, questa classe funziona perfettamente. Sto riscontrando un leggero problema per quanto riguarda i valori predefiniti delle T.
Creo un'istanza di Matrix < int > (3, 3), che crea una matrice 3x3 di ints, il cui valore predefinito è 0 usando default (T). So che i tipi di valore (che includono le primitive) sono impostati su un equivalente 0 e i tipi di riferimento sono impostati su null. Mi chiedevo se fosse possibile modificare questo valore predefinito in modo che se un tipo di valore fosse passato a Matrix, sarebbe popolato con 5 ad esempio, anziché 0.
Ho provato a creare la mia struttura (tipo di valore), ma a causa della mancanza di costruttori senza parametri all'interno di strutture, non riesco a trovare un modo per modificare il valore predefinito da 0.
Sospetto che non sia possibile modificare il valore predefinito e dovrò passare in rassegna la cella Matrix per cella dopo che è stata istanziata, ma volevo chiedere qui nel caso prima di farlo.
Soluzione
public Matrix(int width, int height) : this(width, height, default(T)) {}
public Matrix(int width, int height, T defaultValue)
{
List<T> rows = new List<T>(height);
for (int i = 0; i < height; i++)
{
List<T> columns = new List<T>(width);
for (int j = 0; j < width; j++)
{ columns.Add(defaultValue); }
rows.Add(columns);
}
// store `rows` wherever you are storing it internally.
}
Ma come dice Joseph, non c'è modo di impostare ciò a cui default(T)
valuta.
Altri suggerimenti
Non c'è modo di cambiare il valore predefinito come quello che stai descrivendo.
var someInt = default(int); //this will always be 0, you can't change it
var someReference = default(SomeClass); //this will always be null
Ecco un articolo msdn su di esso , sebbene non sia molto più descrittivo di quello che è già stato detto sfortunatamente.
Puoi creare una struttura che incapsula il suo valore e lo espone solo con un offset del valore predefinito che desideri:
public struct DefaultFiveInteger {
private int _value;
public DefaultFiveInteger(int value) {
_value = x - 5;
}
public static implicit operator int(DefaultFiveInteger x) {
return x._value + 5;
}
public static implicit operator DefaultFiveInteger(int x) {
return new DefaultFiveInteger(x);
}
}
Ora puoi dichiarare una variabile inizializzata sul valore predefinito (0) e restituirà il valore con l'offset:
DefaultFiveInteger x;
Console.Write(x);
Output:
5
Bene, dato che stai già osservando le strutture, potresti simulare un valore predefinito come segue:
public struct MyInt
{
private int _defaultInt;
public int DefaultInt
{
get
{
if (_defaultInt == 0)
return 5;
else
return _defaultInt;
}
set
{
_defaultInt = value;
}
}
}
La mia comprensione dell'implementazione di default(T)
è che il runtime, per impostazione predefinita, azzera la memoria quando l'applicazione lo richiede e C # alloca semplicemente lo spazio senza mai sovrascrivere gli zeri. Accade solo che i valori predefiniti di tipi non numerici (ad es. Riferimento null, false) siano rappresentati come zeri in memoria. Questo può portare ad alcuni comportamenti strani; ad esempio, default(MyEnumType)
sarà zero anche se non hai mai specificato un valore enum uguale a zero.
Combinando le idee di Guffa e DougJones potresti compensare un membro che sostiene le proprietà.
public struct MyInt
{
private const int INT_DEFAULT = 5;
private int _defaultInt;
public int DefaultInt
{
get { return _defaultInt + INT_DEFAULT; }
set { _defaultInt = value - INT_DEFAULT; }
}
}