سؤال

بحسب [MSDN:إرشادات استخدام المصفوفة](http://msdn.microsoft.com/en-us/library/k2604h5s(VS.71).aspx):

خصائص صفيف القيمة

يجب عليك استخدام المجموعات لتجنب عدم كفاءة التعليمات البرمجية.في مثال التعليمات البرمجية التالي، يقوم كل استدعاء للخاصية myObj بإنشاء نسخة من الصفيف.ونتيجة لذلك، سيتم إنشاء نسخ 2n+1 من المصفوفة في الحلقة التالية.

[Visual Basic]

Dim i As Integer
For i = 0 To obj.myObj.Count - 1
   DoSomething(obj.myObj(i))
Next i

[C#]
for (int i = 0; i < obj.myObj.Count; i++)
      DoSomething(obj.myObj[i]);

بخلاف التغيير من myObj[] إلى ICollection myObj، ما الذي ستوصي به أيضًا؟أدركت للتو أن تطبيقي الحالي يسرب الذاكرة :(

شكرًا؛

يحرر:هل سيؤدي إجبار C# على تمرير المراجع مع المرجع (السلامة جانبًا) إلى تحسين الأداء و/أو استخدام الذاكرة؟

هل كانت مفيدة؟

المحلول

لا، ليس كذلك تسرب الذاكرة - إنها تجعل أداة تجميع البيانات المهملة تعمل بجهد أكبر مما قد تفعله.في الواقع، مقالة MSDN مضللة بعض الشيء:إذا أنشأت الخاصية ملفًا جديدًا مجموعة في كل مرة يتم استدعاؤها، سيكون الأمر سيئًا تمامًا (من حيث الذاكرة) كما هو الحال مع المصفوفة.وربما يكون الأسوأ من ذلك، بسبب الحجم الزائد المعتاد لمعظم تطبيقات التجميع.

إذا كنت تعلم أن الطريقة/الخاصية تعمل، فيمكنك دائمًا تقليل عدد المكالمات:

var arr = obj.myObj; // var since I don't know the type!
for (int i = 0; i < arr.Length; i++) {
  DoSomething(arr[i]);
}

أو حتى أسهل، استخدم foreach:

foreach(var value in obj.myObj) {
  DoSomething(value);
}

كلا الطريقتين تتصلان بالعقار مرة واحدة فقط.والثاني هو أوضح المنظمة البحرية الدولية.

أفكار أخرى؛سمها طريقة!أي. obj.SomeMethod() - وهذا يضع التوقع بأنه يعمل، ويتجنب ما هو غير مرغوب فيه obj.Foo != obj.Foo (وهو ما سيكون عليه الحال بالنسبة للمصفوفات).

أخيرًا، إريك ليبرت لديه ميزة جيدة مقالة حول هذا الموضوع.

نصائح أخرى

فقط كتلميح لأولئك الذين لم يستخدموا ReadOnlyCollection المذكورة في بعض الإجابات:

[C#]

class XY
{
  private X[] array;

  public ReadOnlyCollection<X> myObj
  {
    get
    {
      return Array.AsReadOnly(array);
    }
  }
}

نأمل أن يكون هذا قد يساعد.

عندما يكون لدي خصائص مكلفة (مثل إعادة إنشاء مجموعة عند الطلب)، إما أن أقوم بتوثيق الخاصية، مع الإشارة إلى أن كل مكالمة تترتب عليها تكلفة، أو أقوم بتخزين القيمة مؤقتًا كحقل خاص.يجب كتابة أدوات الحصول على الممتلكات باهظة الثمن كطرق.بشكل عام، أحاول عرض المجموعات على أنها IEnumerable بدلاً من المصفوفات، مما يجبر المستهلك على استخدام foreach (أو العداد).

لن يقوم بعمل نسخ من المصفوفة إلا إذا قمت بذلك.ومع ذلك، فإن مجرد تمرير المرجع إلى مصفوفة مملوكة بشكل خاص لكائن ما له بعض الآثار الجانبية السيئة.من يتلقى المرجع هو في الأساس حر في فعل ما يحلو له بالمصفوفة، بما في ذلك تغيير محتوياتها بطرق لا يمكن لمالكها التحكم فيها.

إحدى طرق منع التدخل غير المصرح به في المصفوفة هي إعادة نسخة من محتوياتها.آخر (أفضل قليلاً) هو إرجاع مجموعة للقراءة فقط.

ومع ذلك، قبل القيام بأي من هذه الأشياء، يجب أن تسأل نفسك إذا كنت على وشك الكشف عن الكثير من المعلومات.في بعض الحالات (في الواقع، في كثير من الأحيان) يكون من الأفضل الحفاظ على خصوصية المصفوفة والسماح بتوفير الأساليب التي تعمل على الكائن الذي يمتلكها بدلاً من ذلك.

لن يقوم myobj بإنشاء عنصر جديد إلا إذا قمت بإنشاء عنصر جديد بشكل صريح.لذا، لتحسين استخدام الذاكرة، أوصي باستخدام المجموعة الخاصة (قائمة أو أي منها) وكشف المفهرس الذي سيعيد القيمة المحددة من المجموعة الخاصة

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top