在声明一个 int 数组时,例如:
int[] test = new int[5];
数组的所有元素都自动初始化为0
. 无论如何我可以创建一个在创建数组(例如 int 数组)时自动初始化的类?
例如:
MyClass[] test2 = new MyClass[5];
仍然需要我调用构造函数;但是int
构造函数被神奇地调用了。
int
允许这种行为的类的哪些代码/操作符?
这里的问题是 MyClass 是一个引用类型,所以默认值为 null。因为您没有初始化数组中的对象,所以它们为空。您可以编写一个助手,例如:
T[] InitializeArray<T>(int length) where T : new()
{
T[] array = new T[length];
for (int i = 0; i < length; ++i)
{
array[i] = new T();
}
return array;
}
然后初始化你的数组:
MyClass[] something = InitializeArray<MyClass>(5);
int
数组并没有神奇地设置为 0。它Int
是一个默认值为 0 的值类型,而MyClass
引用类型的默认值为null
.
如果要创建一个所有内容都初始化的数组,可以使用流畅的扩展方法:
public static T[] InitializeAll<T>(this T[] source) where T : new()
{
if(source != null)
{
for(var i = 0; i < source.Length; ++i)
{
source[i] = new T();
}
}
return source;
}
var test2 = new MyClass[5].InitializeAll();
或 mandaleeka 解决方案,使用循环。
编辑:我正在恢复我原来的解决方案,因为 Guffa 的评论需要它作为上下文
public static T[] CreateArray<T>(int size) where T : new()
{
return Enumerable.Repeat(new T(), size).ToArray();
}
更新:
我删除了new()
接受没有无参数构造函数的类的约束。但是,这也将接受抽象类或接口用作类型参数,如果无法实例化类型,它将在运行时抛出异常。
还要提到的一件事是,该CreateArray<T>
方法还将处理值类型;也就是说,除了指针类型和具有TypeAttributes.Abstract
1属性的类型之外,您可以使用它创建任何类型的数组。
1:接口也是抽象的。静态类是抽象和密封的。
不同之处在于它int
是一种值类型,但您class
可能不是。
声明MyClass
为,那么它的行为与您创建数组struct MyClass{ }
的行为相同。int
如果您确实想创建一个引用类型数组,那么下面的代码就是这样做的:
public static class TestClass {
public static T[] CreateArray<T>(int length, params object[] args) {
var elementType=typeof(T);
var array=(T[])Array.CreateInstance(elementType, length);
for(; length-->0;
array[length]=(T)Activator.CreateInstance(elementType, args))
;
return array;
}
public static void TestMethod() {
var array=CreateArray<MyClass>(5, /* default arguments */ );
}
}
默认参数是您传递给构造函数的参数。该代码创建一个数组,然后使用给定的参数创建该类型的实例,并使用这些实例初始化该数组。
请注意,length
作为数组大小传递,然后在 for 循环中用作索引。
文档:
将 MyClass 更改为 struct 数据类型,即:public struct MyClass
。
这与Value Types 和 Reference Types之间的区别有关。
“如果数据类型在自己的内存分配中保存数据,那么它就是值类型。” 而“引用类型包含指向另一个保存数据的内存位置的指针”。
值类型的常见示例:
引用类型的常见示例:
所有值类型都初始化为默认值(数字类型为零),引用类型指向null
.
声明:
int num;
不初始化变量num
。因此num
不能使用。C# 要求在使用每个变量null
之前将其设置为某个值(无论是数字还是数字)。
引用类型也是如此:
//un-initialized, therefore cannot be used until a value is given(A compiler error will occur)
string str;
但是,声明:
int[] numbers = new int[5];
初始化数组(因此调用数组的构造函数),然后将每个元素初始化为 int 的默认值(即零)。
在引用类型上使用相同的方法会产生相同的结果:
string[] strings = new string[5];
导致数组被初始化并因此创建一个null
字符串数组(这是所有引用类型的默认值)。
结构是您正在寻找的数据类型。结构是值类型,因此不能设置为null
. 由于它们不能设置为null
,因此它们必须具有一些默认值。默认值由默认构造函数确定。
一个结构可以这样定义:
struct MyStructName
{
//Members of the struct, like a class, default value is 0.
int myNumber;
//Structs can have members whose data type is a reference type
//Default value is null.
string myString;
//Every struct has a default constructor, though you cannot define one.
//The compiler generates one for you that initializes every member to it's
//default value.
}
这将定义一个数据类型,其中包含不能设置为的成员 myNumber 和 myString null
。
//Array of MyStructName, the default constructor is called and each value is initialized
MyStructName[] data = new MyStructName[5];
//Loop and print results
for(int i = 0; i < data.Length; i++)
{
//Prints the index, number and the string or "null"
Console.WriteLine("{0}: myNumber: {1}, myString: \"{2}\"", i, data[i].myNumber, data[i].myString != null ? data[i].myString : "null");
}