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.

È stato utile?

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; }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top