【问题标题】:How can I quickly up-cast object[,] into double[,]?如何快速将 object[,] 转换为 double[,]?
【发布时间】:2011-07-02 07:09:49
【问题描述】:

我使用Microsoft.Office.Interop.Excel 返回一个object[,] 类型的二维数组,其中包含元素的double。请注意,索引下限是1,而不是默认的0,但我可以轻松处理。

如何很好地使用 .NET 3.5 将数组转换为 double[,]。 (我的意思是简洁或紧凑)。

注意

double[] values_2 = values.Cast<double>().ToArray();

确实有效,但它通过数组扁平化为一维结构。

【问题讨论】:

  • 没有“快速”的方法来做到这一点。如果这是您想要的,您必须将所有数据复制到一个新数组中。
  • 我害怕那个。 .NET 4.0 呢?是否会有一种类型安全的方式来执行 Office 互操作?
  • 快速如“no cpu”或快速如“a-one-line-statement”
  • 你可以用 linq 在一行中完成它,但在计算能力方面它不会更快。
  • 我应该补充一点,两个不同的数组(double 的二维数组和object 的二维数组,索引从 1 开始)是非常不同的对象。没有办法在它们之间进行转换。

标签: c# vb.net office-interop


【解决方案1】:
object[,] src = new object[2, 3];

// Initialize src with test doubles.
src[0, 0] = 1.0;
src[0, 1] = 2.0;
src[0, 2] = 3.0;
src[1, 0] = 4.0;
src[1, 1] = 5.0;
src[1, 2] = 6.0;

double[,] dst = new double[src.GetLength(0), src.GetLength(1)];
Array.Copy(src, dst, src.Length);

【讨论】:

  • 这会很好用,因为我也可以反向使用它,将值放回 Excel。忘记 LINQ,使用 Array 的 Dotnet v1.0 好的旧静态函数。
  • 与使用 for 循环手动执行相比,这非常快。去老 skool .Net 技巧!
  • 它是否适用于 int[,] 到 ushort[,] 以及没有溢出?
  • 请注意,在 VB.NET 中,您需要在将 GetLength 的结果传递给构造函数之前对其进行调整,因为 VB.NET 大小的数组初始值设定项不占用长度,而是占用最大索引。
【解决方案2】:

只要您不做任何愚蠢的事情,我不会说有一种方法比另一种方法更快。我想说的是,如果可以的话,请在访问它们时而不是预先投射它们。当然,这取决于您打算如何访问它们。如果您要多次索引到数组中,那么拆箱的成本可能会开始变得过高。如果您只扫描一次数组,则随走随投。

【讨论】:

    【解决方案3】:

    这在大多数情况下应该可以工作,但如果您不分配转换委托,可能会引发异常。

    public static TResult[,] Convert<TSource, TResult>(
        this TSource[,] array, Func<TSource, TResult> conversion = null) {
    
            if(array == null) throw new ArgumentNullException("array");
    
            if (conversion == null) {
                var resultType = typeof(TResult);
                conversion = source => (TResult)System.Convert.ChangeType(source, resultType);
            }
    
            var width = array.GetLength(1);
            var height = array.GetLength(0);
            var result = new TResult[height, width]; 
    
            for (int i = 0; i < height; ++i)
                for (int j = 0; j < width; ++j)
                    result[i, j] = conversion(array[i, j]);
    
            return result;
        }
    

    【讨论】:

    • 谢谢,但逐个元素的转换效率不高,绝对不是一个不错的解决方案。很高兴在这里为后代保留这个。
    • 我同意,它有点难看,但应该在更广泛的情况下有用,而不仅仅是处理 Excel 的对象数组。默认行为当然很慢,但传入适当的委托可以大大加快速度。
    • 公认的解决方案可以很好地完成工作,无需手持。
    【解决方案4】:

    这里有几个问题。

    首先,由于double 不是引用类型,因此必须将其装箱以存储在 object[] 中,因此获取值的唯一方法是将值拆箱为 double[](复制副本) .

    另一个问题是,在 C# 中,数组是协变的,但不是逆变的,您可以将数组分配给派生较多的类型的引用,而不是派生较少的类型。

    string[] strings = new string[10];
    object[] objects = strings; // OK, covariant
    string[] strings2 = objects; // not OK, contravariant
    objects[0] = 10; // Compiles fine, runtime ArrayTypeMismatchException!
    

    【讨论】:

      【解决方案5】:
      Array.Copy(src, dst, src.Length);
      

      如果 src 中的任何 value 为空,则此代码将出错。

      由于在上面的代码中 src 有一个定义的值,它可以正常工作。

      如果 src 的值是动态设置的,不幸的是,如果其中任何一个值为 null,上述代码将不起作用,因为不会复制 value成功。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-15
        • 2010-11-09
        相关资源
        最近更新 更多