هل من الممكن تحويل C # مزدوجة [،] صفيف لمضاعفة [] دون عمل نسخة

لدي صفائف ضخمة ثلاثية الأبعاد في تطبيق .NET. ولست بحاجة إلى تحويلها إلى مجموعة 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;
0
وأضاف
الآراء: 1

5 إجابة

لسوء الحظ ، لا يمكن ضمان وجود صفيفات C# في ذاكرة متجاورة مثلما هي في لغات أقرب إلى المعدن مثل C. So، no. لا توجد طريقة لتحويل double [،] إلى مضاعفة [] بدون نسخة عنصري لكل عنصر.

0
وأضاف

دون معرفة تفاصيل مكتبة COM الخاصة بك ، سوف أنظر إلى إنشاء فئة واجهة في .Net وتعريضها إلى COM ، إذا لزم الأمر. ستأخذ واجهتك ثنائية [،] وستحصل على مفهرس سيتم تعيينه من [] إلى [،].

تعديل: أوافق على النقاط الواردة في التعليقات ، اقتراح لورينز أفضل.

0
وأضاف
لا أتمكن من تغيير مكتبة COM.
وأضاف المؤلف Hallgrim, مصدر
هذا لن ينجح. ستحتاج إلى إلى صفيف مزدوجة []. إذا كان هناك أي شيء ، فستحتاج إلى إنشاء فئة .NET تجعل الفعل المزدوج [] بمثابة مزدوج [،].
وأضاف المؤلف Jonathan Rupp, مصدر

كحل بديل ، يمكنك إنشاء فئة تحافظ على الصفيف في شكل واحد الأبعاد (ربما حتى في شكل أقرب إلى المعدن المجرد بحيث يمكنك تمريره بسهولة إلى مكتبة COM؟) ومن ثم حمل المشغل [] على هذا الصف لجعله قابل للاستخدام كمصفف متعدد الأبعاد في كود C# الخاص بك.

0
وأضاف

لا أصدق الطريقة التي تخزن بها C# أن البيانات في الذاكرة ستجعلها مجدية بنفس الطريقة التي سيؤديها المصبوب في C. لماذا لا تستخدم صفيف 1d لتبدأ به وربما تصنع فئة للنوع بحيث يمكنك الوصول إليه في برنامجك كما لو كان مصفوفة ثلاثية الأبعاد؟

0
وأضاف

يمكنك التفكير في استخراج الوصول إلى البيانات باستخدام الخادم الوكيل (على غرار المتكررات/المؤشرات الذكية في C ++) . لسوء الحظ ، ليس بناء الجملة نظيفًا مثل C ++ لأن المشغل() غير متوفر للتحميل الزائد و عامل التشغيل [] هو arg مفرد ، ولكنه لا يزال مغلقًا.

وبالطبع ، فإن هذا المستوى الإضافي من التجريد يضيف تعقيدات وعمل خاص به ، ولكنه سيسمح لك بإجراء تغييرات بسيطة على الكود الحالي الذي يستخدم مضاعف [،] الكائنات ، بينما يسمح لك باستخدام صفيف [] مزدوج واحد لكل منهما interop وحساب 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;
    }
}

مرة أخرى ، إضافة تكاليف التطوير ، ولكن مشاركة البيانات ، وإزالة تكاليف النسخ والنسخ المتعلقة بالتطوير. إنها مقايضة

0
وأضاف