Pregunta

Recientemente creé una matriz genérica < T > clase que actúa como un contenedor alrededor de una Lista < Lista < T > > colección. Por lo que puedo decir, esta clase está funcionando perfectamente. Sin embargo, me encuentro con un pequeño problema con respecto a los valores predeterminados de las T.

Creo una instancia de Matrix < int > (3, 3), que crea una matriz de entradas 3x3, todas predeterminadas a 0 usando el valor predeterminado (T). Sé que los tipos de valor (que incluyen primitivas) tienen un valor predeterminado de 0 equivalente, y los tipos de referencia tienen un valor predeterminado de nulo. Me preguntaba si era posible cambiar este valor predeterminado para que si se pasa un tipo de valor a Matrix, se rellenaría con 5, por ejemplo, en lugar de 0.

Intenté crear mi propia estructura (tipo de valor), pero debido a que no puedo usar constructores sin parámetros dentro de estructuras, no puedo encontrar una manera de cambiar el valor predeterminado de 0.

Sospecho que no es posible cambiar el valor predeterminado, y tendré que recorrer la Matriz celda por celda después de que se haya instanciado, pero quería preguntar aquí por si acaso antes de hacerlo.

¿Fue útil?

Solución

 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.
 }

Pero como dice Joseph, no hay forma de establecer lo que default(T) evalúa.

Otros consejos

No hay forma de cambiar el valor predeterminado, como se describe.

var someInt = default(int); //this will always be 0, you can't change it
var someReference = default(SomeClass); //this will always be null

Aquí hay un artículo msdn en él , aunque lamentablemente no es mucho más descriptivo de lo que ya se ha dicho.

Puede crear una estructura que encapsule su valor y solo la exponga con un desplazamiento del valor predeterminado que desee:

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);
   }

}

Ahora puede declarar una variable que se inicializa al valor predeterminado (0), y devolverá el valor con el desplazamiento:

DefaultFiveInteger x;
Console.Write(x);

Salida:

5

Bueno, dado que ya está viendo estructuras, puede simular un valor predeterminado de la siguiente manera:

public struct MyInt
{
    private int _defaultInt;
    public int DefaultInt
    {
        get
        {
            if (_defaultInt == 0)
                return 5;
            else
                return _defaultInt;
        }
        set
        {
            _defaultInt = value;
        }
    }
}

Entiendo que la implementación de default(T) es que el tiempo de ejecución, de forma predeterminada, elimina la memoria a medida que la aplicación lo solicita, y C # simplemente asigna el espacio sin sobrescribir los ceros. Sucede que los valores predeterminados de los tipos no numéricos (por ejemplo, la referencia nula, falso) se representan como ceros en la memoria. Esto puede conducir a un comportamiento extraño; por ejemplo, default(MyEnumType) será cero incluso si nunca especificó un valor de enumeración igual a cero.

Combinando las ideas de Guffa y DougJones, podría compensar un miembro de respaldo de propiedades.

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; }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top