Недавно я создал общую матрицу <T> класс, который действует как обертка вокруг списка < List <T → > коллекция. Насколько я могу судить, этот класс работает отлично. Я столкнулся с небольшой проблемой, хотя в отношении значений по умолчанию для T.
Я создаю экземпляр Matrix <int> (3, 3), который создает матрицу 3x3 из ints, все по умолчанию равны 0, используя значение по умолчанию (T). Я знаю, что типы значений (включая примитивы) по умолчанию эквивалентны 0, а ссылочные типы по умолчанию равны нулю. Мне было интересно, можно ли изменить это значение по умолчанию, чтобы, если тип значения передается в матрицу, он будет заполнен, например, 5, а не 0.
Я попытался создать свою собственную структуру (тип значения), но из-за того, что я не мог использовать конструкторы без параметров внутри structs, я не могу найти способ изменить значение по умолчанию из 0.
Я подозреваю, что изменить значение по умолчанию невозможно, и мне придется прокручивать ячейку Matrix по ячейке после ее создания, но я хотел спросить здесь на всякий случай, прежде чем я это сделаю.
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 article, хотя это не намного более описательно, чем то, что уже было сказано к сожалению.
Вы можете создать структуру, которая инкапсулирует ее значение и выставляет ее только со смещением значения по умолчанию, которое вы хотите:
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
int Value
get / set, так как вывод типа не достаточен, чтобы позволить сделать все с DefaultFiveInteger
что можно сделать с int
(например, если у него есть DefaultFiveInteger d5
и DefaultSixInteger d6
Можно сказать, d6 = (int)d5
, но, возможно, было бы чище сказать d6.Value = d5.Value;
Объединив идеи Guffa и DougJones, вы могли бы компенсировать элемент поддержки свойств.
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; }
}
}
MyInt<T> where T:IIntDefaultSupplier,new()
, где IIntDefaultReporter содержит метод GetDefaultValue()
. MyInt<T>
Класс будет содержать статическое значение по умолчанию, которое будет загружено при первом использовании путем создания нового экземпляра T
и вызова GetDefaultValue()
для него. Кроме того, я бы предложил использовать xor вместо +/-, чтобы избежать проблем с переполнением целых чисел.
Хорошо, так как вы уже смотрите на структуры, вы можете имитировать значение по умолчанию следующим образом:
public struct MyInt
{
private int _defaultInt;
public int DefaultInt
{
get
{
if (_defaultInt == 0)
return 5;
else
return _defaultInt;
}
set
{
_defaultInt = value;
}
}
}
Мое понимание реализации default(T)
заключается в том, что среда выполнения, по умолчанию, выдает из памяти память, когда приложение ее запрашивает, а С# просто выделяет пространство, не перезаписывая нули. Так получилось, что значения по умолчанию для нечисловых типов (например, нулевая ссылка, ложь) представлены как нули в памяти. Это может привести к некоторому странному поведению; например, default(MyEnumType)
будет равно нулю, даже если вы никогда не указывали значение enum равным нулю.