【问题标题】:Array initialization with default constructor使用默认构造函数初始化数组
【发布时间】:2011-06-17 21:21:45
【问题描述】:
public class Sample
{
     static int count = 0;
     public int abc;
     public Sample()
     {
        abc = ++Sample.count;
     }
}

我想创建一个上述类的数组,并希望通过调用默认构造函数来初始化数组中的每个元素,以便每个元素可以有不同的abc。所以我这样做了:

Sample[] samples = new Sample[100];

但这并没有做我认为应该做的事情。似乎这样默认构造函数没有被调用。创建数组时如何调用默认构造函数?

我也想知道上面的语句是做什么用的?

【问题讨论】:

  • 你为什么不只使用数组索引,它的唯一性和根据你的代码自动递增
  • 附带说明 - 代码不是线程安全的;您应该改用id = Interlocked.Increment(ref count),并以static int count = 1 开头(因为Interlocked.Increment 返回 值)。
  • 在上面的代码中,您刚刚声明了一个大小为 100 的数组,其中没有任何项目。
  • @Ivanov 如果他这样做了,当他从数组中拉出一个项目时,他将不会拥有该对象的唯一标识符。
  • 旁注:但如果您不使用多线程 - 不要使用 Interlocked.Increment 而不是 ++。

标签: c# arrays default-constructor array-initialize


【解决方案1】:

你不能,基本上。当你创建一个数组时,它最初总是用类型的默认值填充——对于一个类来说,它总是一个空引用。 int 为 0,bool 为 false,等等。

(如果您使用数组初始值设定项,这将创建“空”数组并然后用您指定的值填充它,当然。)

有多种方法可以通过调用构造函数来填充数组 - 我可能自己只使用一个 foreach 循环。将 LINQ 与 Enumerable.Range/Repeat 一起使用感觉有点勉强。

当然,您总是可以编写自己的填充方法,甚至作为扩展方法:

public static T[] Populate<T>(this T[] array, Func<T> provider)
{
    for (int i = 0; i < array.Length; i++)
    {
        array[i] = provider();
    }
    return array;
}

那么你可以使用:

Sample[] samples = new Sample[100].Populate(() => new Sample());

我喜欢这个解决方案的地方:

  • 仍然是单个表达式,可以在各种场景中使用
  • 它不会引入您实际上不想要的概念(例如重复单个值或创建范围)

当然你可以添加更多选项:

  • 采用Func&lt;int, T&gt; 而不是Func&lt;T&gt; 的重载,将索引传递给提供者
  • 一种创建数组填充它的非扩展方法

【讨论】:

  • 我最喜欢这个解决方案。 :-) 可重用的方法。 :-)
  • 另一个有用的重载是将, Func&lt;T&gt; provider)替换为) where T : new(),然后如果您只是使用默认构造函数,则根本不需要传递委托(您还需要替换@ 987654329@ 和 new T())。
【解决方案2】:

您的代码仅创建 数组,但没有创建任何项目。基本上,您需要将Sample 的实例存储到这个数组中。

简单地说,没有任何花哨的 LINQ 等:

Sample[] samples = new Sample[100];
for (int i = 0; i < samples.Length; i++) samples[i] = new Sample();

另请注意,您的解决方案不是线程安全的。

【讨论】:

    【解决方案3】:

    无法自动执行此操作;数组初始化本质上是“将这块内存擦除为 0”。您必须执行以下操作:

    var arr = new SomeType[size];
    for(int i = 0 ; i < size ; i++) arr[i] = new SomeType();
    

    【讨论】:

      【解决方案4】:

      此时你有一个大小为 100 的空数组,如果你想用项目填充它,那么你必须执行以下操作:

      for(int i=0; i<samples.Length; i++) {
         samples[i] = new Sample();
      }
      

      【讨论】:

        【解决方案5】:

        问题在于,通过声明该数组,您从未为每个对象分配空间。您只是为 100 个 Sample 类型的对象分配了空间。您必须自己调用每个构造函数。

        详细说明:

        Food[] foods = Food[100];
        for (int k = 0; k < foods.length; k++) {
           foods[k] = new Food();
        }
        

        一个有趣的解决方法可能是工厂函数。考虑将此附加到您的示例类。

        public static Sample[] getInstances(int aNumber) {
            Sample[] sample = Sample[aNumber];
            for (int k = 0; k < sample.length; k++) {
               sample[k] = new Sample();
            }
        
            return sample;
        }
        

        隐藏瑕疵,有点 - 如果这是对您有用的功能。

        【讨论】:

        • 我用您可能喜欢的解决方案对其进行了编辑。不过,简短的回答是肯定的。 ://
        • 您正在创建Food 的数组,但返回类型为Sample[]:P
        【解决方案6】:

        这是另一个不需要任何扩展方法的单行代码:

        Sample[] array = Enumerable.Range(0, 100).Select(i => new Sample()).ToArray();
        

        另一个不错的选择是Scott's suggestionJon's answer

        public static T[] Populate<T>(this T[] array) 
            where T : new()
        {
            for (int i = 0; i < array.Length; i++)
                array[i] = new T();
            return array;
        }
        

        所以你可以这样做:

        Sample[] array = new Sample[100].Populate();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-17
          • 2015-07-10
          • 2011-06-12
          • 2012-01-02
          相关资源
          最近更新 更多