Is it possible to change the default value of a primitive data type?
-
05-07-2019 - |
Question
I recently created a generic Matrix<T> class that acts as a wrapper around a List<List<T>> collection. As far as I can tell, this class is working perfectly. I am running into a slight problem though regarding the default values of the T's.
I create an instance of Matrix<int>(3, 3), which creates a 3x3 matrix of ints, all defaulted to 0 using default(T). I know that value types (which include primitives) default to a 0 equivalent, and reference types default to null. I was wondering if it was possible to change this default value so that if a value type is passed into the Matrix, it would be populated with 5's for example, instead of 0's.
I tried creating my own struct (value type), but due to not being able to use parameterless constructors inside structs, I cannot find a way to change the default value from 0.
I suspect changing the default value is not possible, and I will have to loop through the Matrix cell by cell after it has been instantiated, but I wanted to ask on here just in case before I do that.
Solution
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.
}
But as Joseph says, there's no way of setting what default(T)
evaluates to.
OTHER TIPS
There's no way to change the default value like how you're describing.
var someInt = default(int); //this will always be 0, you can't change it
var someReference = default(SomeClass); //this will always be null
Here's an msdn article on it, although it's not much more descriptive than what's already been said unfortunately.
You can make a structure that encapsulates it's value and only exposes it with an offset of the default value that you want:
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);
}
}
Now you can declare a variable that is initialised to the default value (0), and it will return the value with the offset:
DefaultFiveInteger x;
Console.Write(x);
Output:
5
Well since you're looking at structs already, you could simulate a default value as follows:
public struct MyInt
{
private int _defaultInt;
public int DefaultInt
{
get
{
if (_defaultInt == 0)
return 5;
else
return _defaultInt;
}
set
{
_defaultInt = value;
}
}
}
My understanding of the implementation of default(T)
is that the runtime, by default, zeros out the memory as the application requests it, and C# just allocates the space without ever overwriting the zeros. It just so happens that the default values of non-numeric types (e.g. the null reference, false) are represented as zeros in memory. This can lead to some weird behavior; for example, default(MyEnumType)
will be zero even if you never specified an enum value to be equal to zero.
Combining Guffa's and DougJones ideas you could offset a properties backing member.
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; }
}
}