如何创建元素自动实例化数组,例如用户定义类型的 int 数组

本文关键字:数组 用户 定义 int 类型 何创建 创建 元素 实例化 | 更新日期: 2023-09-27 18:20:04

在声明一个 int 数组时,例如:

int[] test = new int[5];

数组的所有元素都自动初始化为 0 。无论如何,我可以创建一个在创建数组(例如 int 数组(时自动初始化的类吗?

例如:

MyClass[] test2 = new MyClass[5];

仍然需要我调用构造函数;但有了int构造函数就会神奇地调用。

允许此行为的 int 类的哪些代码/运算符?

如何创建元素自动实例化数组,例如用户定义类型的 int 数组

这里的问题是MyClass是一个引用类型,所以默认值为null。由于不初始化数组中的对象,因此它们为 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 的值类型,而 as 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();

或者曼达利卡解决方案,使用循环。

编辑:我正在恢复我的原始解决方案,因为 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 循环中用作索引。

文档:

  • Activator.CreateInstance

  • Array.CreateInstance

将 MyClass 更改为结构数据类型,即:public struct MyClass

这与值类型和引用类型之间的差异有关。

">

如果数据类型将数据保存在自己的内存分配中,则数据类型是值类型",而"引用类型包含指向保存数据的另一个内存位置的指针。

值类型的常见示例:

  • 所有数值数据类型
  • 布尔值、字符和日期
  • 所有结构,即使其成员是引用类型
  • 枚举,因为它们的基础类型始终为 SByte、Short、Integer、Long、Byte、Short、UInteger 或 ULong

引用类型的常见示例:

  • 字符串
  • 所有数组,即使它们的元素是值类型
  • 类类型,例如表单
  • 代表

所有值类型都初始化为默认值(数值类型为零(,引用类型指向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.
}

这将定义一个数据类型,其中包含不能设置为 null 的成员 myNumber 和 myString。

//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"); 
}