簡體   English   中英

是否可以將C#double [,,]數組轉換為double []而無需復制

[英]Is is possible to convert C# double[,,] array to double[] without making a copy

我的.NET應用程序中有大量的3D數組。 我需要將它們轉換為1D數組以將其傳遞給COM庫。 有沒有辦法轉換數組而不復制所有數據?

我可以像這樣進行轉換,但后來我使用了兩倍的內存量,這是我的應用程序中的一個問題:

  double[] result = new double[input.GetLength(0) * input.GetLength(1) * input.GetLength(2)];
  for (i = 0; i < input.GetLength(0); i++) 
    for (j = 0; j < input.GetLength(1); j++) 
      for (k = 0; k < input.GetLength(2); k++) 
        result[i * input.GetLength(1) * input.GetLength(2) + j * input.GetLength(2) + k)] = input[i,j,l];
  return result;

我不相信C#將數據存儲在內存中的方式可以像C中的簡單轉換一樣使其可行。 為什么不使用1d數組開始,也許為類型創建一個類,以便您可以在程序中訪問它,就像它是一個3d數組一樣?

不幸的是,C#數組並不能保證在連續的內存中,就像它們是像C這樣更接近金屬的語言。所以,沒有。 如果沒有逐個元素的副本,就無法將double [,,]轉換為double []。

考慮用代理抽象訪問數據(類似於C ++中的迭代器/智能指針)。 不幸的是,語法並不像C ++那樣干凈,因為operator()不能用於重載,而operator []是單arg,但仍然很接近。

當然,這種額外的抽象級別會增加其自身的復雜性和工作量,但它允許您對使用雙[,,]對象的現有代碼進行最小的更改,同時允許您對兩者使用單個double []數組互操作和你的in-C#計算。

class Matrix3
{
    // referece-to-element object
    public struct Matrix3Elem{
        private Matrix3Impl impl;
        private uint dim0, dim1, dim2;
        // other constructors
        Matrix3Elem(Matrix3Impl impl_, uint dim0_, uint dim1_, uint dim2_) {
            impl = impl_; dim0 = dim0_; dim1 = dim1_; dim2 = dim2_;
        }
        public double Value{
            get { return impl.GetAt(dim0,dim1,dim2); }
            set { impl.SetAt(dim0, dim1, dim2, value); }
        }
    }

    // implementation object
    internal class Matrix3Impl
    {
        private double[] data;
        uint dsize0, dsize1, dsize2; // dimension sizes
        // .. Resize() 
        public double GetAt(uint dim0, uint dim1, uint dim2) {
            // .. check bounds
            return data[ (dim2 * dsize1 + dim1) * dsize0 + dim0 ];
        }
        public void SetAt(uint dim0, uint dim1, uint dim2, double value) {
            // .. check bounds
            data[ (dim2 * dsize1 + dim1) * dsize0 + dim0 ] = value;
        }
    }

    private Matrix3Impl impl;

    public Matrix3Elem Elem(uint dim0, uint dim1, uint dim2){
        return new Matrix2Elem(dim0, dim1, dim2);
    }
    // .. Resize
    // .. GetLength0(), GetLength1(), GetLength1()
}

然后使用這種類型進行讀寫 - 'foo [1,2,3]'現在寫成'foo.Elem(1,2,3).Value',在讀取值和寫入值時,賦值和值表達式的左側。

void normalize(Matrix3 m){

    double s = 0;
    for (i = 0; i < input.GetLength0; i++)     
        for (j = 0; j < input.GetLength(1); j++)       
            for (k = 0; k < input.GetLength(2); k++)
    {
        s += m.Elem(i,j,k).Value;
    }
    for (i = 0; i < input.GetLength0; i++)     
        for (j = 0; j < input.GetLength(1); j++)       
            for (k = 0; k < input.GetLength(2); k++)
    {
        m.Elem(i,j,k).Value /= s;
    }
}

同樣,增加了開發成本,但共享數據,消除了復制開銷和復制相關的開發成本。 這是一個權衡。

在不知道COM庫的詳細信息的情況下,我將考慮在.Net中創建一個Facade類,並在必要時將其公開給COM。
你的門面需要一個雙[,,]並有一個將從[]映射到[,,]的索引器。

編輯:我同意評論中提出的觀點,Lorens建議更好。

作為一種解決方法,您可以創建一個以一維形式維護數組的類(甚至可以更接近裸機形式,以便您可以輕松地將其傳遞給COM庫?)然后在此類上重載operator []以使其可用作為C#代碼中的多維數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM