Можно ли изменить значение по умолчанию для примитивного типа данных?
-
05-07-2019 - |
Вопрос
Недавно я создал универсальный класс Matrix<T> , который действует как оболочка вокруг списка<List<T>> коллекция.Насколько я могу судить, этот класс работает отлично.Однако я столкнулся с небольшой проблемой, связанной со значениями T по умолчанию.
Я создаю экземпляр Matrix<int>(3, 3), который создает матрицу целых чисел размером 3x3, для всех по умолчанию установлено значение 0, используя default (T) .Я знаю, что типы значений (которые включают примитивы) по умолчанию эквивалентны 0, а ссылочные типы по умолчанию равны null.Мне было интересно, можно ли изменить это значение по умолчанию, чтобы, если тип значения передается в матрицу, оно было бы заполнено, например, цифрами 5 вместо 0.
Я попытался создать свою собственную структуру (тип значения), но из-за невозможности использовать конструкторы без параметров внутри структур я не могу найти способ изменить значение по умолчанию с 0.
Я подозреваю, что изменение значения по умолчанию невозможно, и мне придется перебирать матрицу ячейка за ячейкой после того, как она будет создана, но я хотел спросить здесь на всякий случай, прежде чем я это сделаю.
Решение
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.
}
Но, как говорит Джозеф, нет способа установить, что default(T)
оценивает.
Другие советы
Нет способа изменить значение по умолчанию, например, как вы описываете.
var someInt = default(int); //this will always be 0, you can't change it
var someReference = default(SomeClass); //this will always be null
Вот статья msdn об этом , хотя это не намного более наглядно, чем, к сожалению, уже сказано.
Вы можете создать структуру, которая инкапсулирует это значение и предоставляет его только со смещением от значения по умолчанию, которое вы хотите:
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);
}
}
Теперь вы можете объявить переменную, которая инициализируется значением по умолчанию (0), и она вернет значение со смещением:
DefaultFiveInteger x;
Console.Write(x);
Выходной сигнал:
5
Ну, так как вы уже просматриваете структуры, вы можете смоделировать значение по умолчанию следующим образом:
public struct MyInt
{
private int _defaultInt;
public int DefaultInt
{
get
{
if (_defaultInt == 0)
return 5;
else
return _defaultInt;
}
set
{
_defaultInt = value;
}
}
}
Мое понимание реализации default(T)
состоит в том, что среда выполнения по умолчанию обнуляет память по мере того, как приложение ее запрашивает, а C # просто выделяет пространство, не перезаписывая нули. Так уж получилось, что значения по умолчанию для нечисловых типов (например, нулевая ссылка, ложь) представлены в памяти как нули. Это может привести к странному поведению; например, default(MyEnumType)
будет равно нулю, даже если вы никогда не указывали значение enum равным нулю.
Комбинируя идеи Гуффы и Дугджонса, вы можете сместить элемент поддержки свойств.
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; }
}
}