【问题标题】:C# Array initialization - with non-default valueC# 数组初始化 - 具有非默认值
【发布时间】:2008-09-25 23:22:34
【问题描述】:

您知道在 C# 中初始化动态大小数组的最巧妙方法是什么?

这是我能想到的最好的了

private bool[] GetPageNumbersToLink(IPagedResult result)
{
   if (result.TotalPages <= 9)
      return new bool[result.TotalPages + 1].Select(b => true).ToArray();

   ...

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    如果“最流畅”是指最快,恐怕 Enumerable.Repeat 可能比 for 循环慢 20 倍。 见http://dotnetperls.com/initialize-array

    Initialize with for loop:             85 ms  [much faster]
    Initialize with Enumerable.Repeat:  1645 ms 
    

    所以使用 Dotnetguy 的 SetAllValues() 方法。

    【讨论】:

      【解决方案2】:

      使用Enumerable.Repeat

      Enumerable.Repeat(true, result.TotalPages + 1).ToArray()
      

      【讨论】:

      • 我认为 Nigel 的业绩说明值得一提 - stackoverflow.com/questions/136836/…
      • 我无法相信人们会为如此“模糊”(在我看来)并且对于像填充数组这样简单的操作而昂贵的东西投赞成票。 var arr = new type[10]; for (int i = 0; i &lt; arr.Length; i++) arr[i] = value;,76 个字符的代码,每个人都能理解 :)。与 67 个字符的模糊性相比。
      【解决方案3】:

      编辑:正如评论者指出的那样,我最初的实现不起作用。这个版本有效,但基于 for 循环相当不灵活。

      如果你愿意创建一个扩展方法,你可以试试这个

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

      然后像这样调用它

      bool[] tenTrueBoolsInAnArray = new bool[10].SetAllValues(true);
      

      作为替代方案,如果您对上课感到满意,您可以尝试这样的方法

      public static class ArrayOf<T>
      {
          public static T[] Create(int size, T initialValue)
          {
              T[] array = (T[])Array.CreateInstance(typeof(T), size);
              for (int i = 0; i < array.Length; i++)
                  array[i] = initialValue;
              return array;
          }
      }
      

      你可以像这样调用它

      bool[] tenTrueBoolsInAnArray = ArrayOf<bool>.Create(10, true);
      

      不确定我更喜欢哪个,尽管我通常会大量使用扩展方法。

      【讨论】:

      • 我不相信您的 SetAllValues 会起作用:在您的 lambda 表达式中,x 不是通过引用传递的,因此为其分配值不会更改存储在数组中的值。
      • 是的,你完全正确。我提到我实际上并没有编译它,这会显示出相当基本的错误。我用一个简单的循环替换了 ForEach 并且效果很好,但它并不像提问者所要求的那样光滑。
      • 除此之外,您的扩展方法有一个签名,暗示它将返回一个新数组,但它会修改原始数组并返回它。格式不好。
      • 一,打电话给你的SetAllValuesFill,我觉得这个名字更好。第二,在第二种情况下利用 C# 的类型推断。所以像这样的声明是可能的:ArrayEx.Create(10, true);.
      • 你不需要Array.CreateInstance,只需new T[]
      【解决方案4】:

      我实际上建议这样做:

      return Enumerable.Range(0, count).Select(x => true).ToArray();
      

      这样你只分配一个数组。这本质上是一种更简洁的表达方式:

      var array = new bool[count];
      
      for(var i = 0; i < count; i++) {
         array[i] = true;
      }
      
      return array;
      

      【讨论】:

      • 甚至 new bool[count].Select(x=>true).ToArray()
      • 那仍然会分配两个数组。
      【解决方案5】:

      很多时候你想用不同的值初始化不同的单元格:

      public static void Init<T>(this T[] arr, Func<int, T> factory)
      {
          for (int i = 0; i < arr.Length; i++)
          {
              arr[i] = factory(i);
          }
      }
      

      或者工厂风味:

      public static T[] GenerateInitializedArray<T>(int size, Func<int, T> factory)
      {
          var arr = new T[size];
          for (int i = 0; i < arr.Length; i++)
          {
              arr[i] = factory(i);
          }
          return arr;
      }
      

      【讨论】:

        【解决方案6】:

        未经测试,但你可以这样做吗?

        return result.Select(p => true).ToArray();
        

        跳过“new bool[]”部分?

        【讨论】:

        • 仅当 IPagedResult : IEnumerable
        猜你喜欢
        • 2020-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-06
        相关资源
        最近更新 更多