Можно ли изменить значение по умолчанию для примитивного типа данных?

2

Недавно я создал общую матрицу <T> класс, который действует как обертка вокруг списка < List <T → > коллекция. Насколько я могу судить, этот класс работает отлично. Я столкнулся с небольшой проблемой, хотя в отношении значений по умолчанию для T.

Я создаю экземпляр Matrix <int> (3, 3), который создает матрицу 3x3 из ints, все по умолчанию равны 0, используя значение по умолчанию (T). Я знаю, что типы значений (включая примитивы) по умолчанию эквивалентны 0, а ссылочные типы по умолчанию равны нулю. Мне было интересно, можно ли изменить это значение по умолчанию, чтобы, если тип значения передается в матрицу, он будет заполнен, например, 5, а не 0.

Я попытался создать свою собственную структуру (тип значения), но из-за того, что я не мог использовать конструкторы без параметров внутри structs, я не могу найти способ изменить значение по умолчанию из 0.

Я подозреваю, что изменить значение по умолчанию невозможно, и мне придется прокручивать ячейку Matrix по ячейке после ее создания, но я хотел спросить здесь на всякий случай, прежде чем я это сделаю.

Теги:
generics
list
struct
value-type

6 ответов

3
Лучший ответ
 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).

  • 0
    Я не думал о добавлении конструктора для определения значения по умолчанию. Хотя не совсем то, что я искал, это довольно изящно, и, безусловно, будет работать!
1

Невозможно изменить значение по умолчанию, например, как вы описываете.

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, хотя это не намного более описательно, чем то, что уже было сказано к сожалению.

1

Вы можете создать структуру, которая инкапсулирует ее значение и выставляет ее только со смещением значения по умолчанию, которое вы хотите:

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
  • 0
    Небольшое примечание: если используется исключение или добавление, код будет работать для всех целочисленных значений даже в проверенном числовом контексте. Кроме того, может быть полезно включить свойство am int Value get / set, так как вывод типа не достаточен, чтобы позволить сделать все с DefaultFiveInteger что можно сделать с int (например, если у него есть DefaultFiveInteger d5 и DefaultSixInteger d6 Можно сказать, d6 = (int)d5 , но, возможно, было бы чище сказать d6.Value = d5.Value;
  • 0
    @supercat: Хорошая точка в проверенном контексте, которая может быть предпочтительнее, хотя она менее интуитивно понятна, как хранятся значения. Наличие установщика для значения может вызвать проблемы (изменяемые структуры обычно не одобряются), но может быть полезен метод получения int.
Показать ещё 13 комментариев
0

Объединив идеи 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; }
    }
}
  • 0
    На самом деле, вы можете использовать MyInt&lt;T&gt; where T:IIntDefaultSupplier,new() , где IIntDefaultReporter содержит метод GetDefaultValue() . MyInt&lt;T&gt; Класс будет содержать статическое значение по умолчанию, которое будет загружено при первом использовании путем создания нового экземпляра T и вызова GetDefaultValue() для него. Кроме того, я бы предложил использовать xor вместо +/-, чтобы избежать проблем с переполнением целых чисел.
0

Хорошо, так как вы уже смотрите на структуры, вы можете имитировать значение по умолчанию следующим образом:

public struct MyInt
{
    private int _defaultInt;
    public int DefaultInt
    {
        get
        {
            if (_defaultInt == 0)
                return 5;
            else
                return _defaultInt;
        }
        set
        {
            _defaultInt = value;
        }
    }
}
  • 0
    Это ломается, если вы явно устанавливаете int равным 0. Ваш код все равно вернет 5.
  • 0
    Правда, если бы я его реализовал, я бы использовал int? тип данных и проверка на ноль. Если он нулевой, вы можете предположить, что он никогда не был установлен, поэтому верните 5.
0

Мое понимание реализации default(T) заключается в том, что среда выполнения, по умолчанию, выдает из памяти память, когда приложение ее запрашивает, а С# просто выделяет пространство, не перезаписывая нули. Так получилось, что значения по умолчанию для нечисловых типов (например, нулевая ссылка, ложь) представлены как нули в памяти. Это может привести к некоторому странному поведению; например, default(MyEnumType) будет равно нулю, даже если вы никогда не указывали значение enum равным нулю.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню