سؤال

أنا كائن متعدد الخيوط البيئة التي تحافظ على مجموعة من المعلومات ، على سبيل المثال:

public IList<string> Data 
{
    get 
    {
        return data;
    }
}

لدي حاليا return data; ملفوفة من قبل ReaderWriterLockSlim لحماية مجموعة من مشاركة انتهاكات.بيد أن تتأكد من مضاعفة, أود العودة جمع للقراءة فقط بحيث استدعاء التعليمات البرمجية غير قادر على إجراء تغييرات على جمع عرض فقط ما هو بالفعل هناك.هل هذا ممكن ؟

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

المحلول

إذا كان القصد الوحيد هو الحصول على كود الاتصال لا تجعل من الخطأ وتعديله جمع عندما ينبغي أن يكون فقط في قراءة كل ما هو ضروري هو العودة إلى واجهة التي لا تدعم إضافة وإزالة الخ..لماذا لا يعود IEnumerable<string>?استدعاء التعليمات البرمجية يجب أن يلقي ، التي من غير المرجح أن تفعل دون معرفة الداخلية من الممتلكات التي يتم الوصول.

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

نصائح أخرى

إذا كان لديك البيانات الأساسية يتم تخزين قائمة كما يمكنك استخدام قائمة(T).AsReadOnly الأسلوب.
إذا كانت البيانات الخاصة بك يمكن حصرها ، يمكنك استخدام Enumerable.ToList طريقة يلقي جمع الخاصة بك إلى قائمة الاتصال AsReadOnly على ذلك.

أنا صوت من أجل الإجابة المقبولة و أتفق مع ذلك-ومع ذلك قد أعطي لك شيء تنظر ؟

لا عودة مجموعة مباشرة.جعل بدقة اسمه منطق الأعمال الدرجة التي تعكس الغرض من جمع.

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

فعلى سبيل المثال ، إذا كانت مجموعتك الفواتير ، سيكون لديك ربما 3 أو 4 أماكن في التعليمات البرمجية الخاصة بك حيث أكد على الفواتير غير المسددة.هل يمكن أن يكون getUnpaidInvoices الأسلوب.ومع ذلك ، فإن القوة الحقيقية تأتي عندما تبدأ في التفكير في أساليب مثل "payUnpaidInvoices(دافع الحساب);".

عند تمرير حول مجموعات بدلا من كتابة كائن نموذج فئات كاملة من refactorings لن تحدث لك.

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

كيف يمكن حل هذه المشكلة عندما يتم تمرير الأصلية جمع ؟

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

أعتقد أنك تخلط بين المفاهيم هنا.

على ReadOnlyCollection يوفر للقراءة فقط المجمع على جمع القائمة, مما يسمح لك (فئة A) لتمرير إشارة إلى جمع آمنة في المعرفة التي المتصل (فئة ب) لا يمكن تعديل جمع (أيلا إضافة أو إزالة أي عناصر من المجموعة.)

هناك على الإطلاق أي موضوع ضمانات السلامة.

  • إذا كنت (فئة أ) مواصلة تعديل الأساسية جمع بعد هذا كما ReadOnlyCollection ثم فئة B سوف نرى هذه التغييرات ، أي التكرار يبطل ، إلخ.و عموما تكون مفتوحة أي من المعتاد قضايا التزامن مع مجموعات.
  • بالإضافة إلى ذلك, إذا كانت العناصر داخل مجموعة قابلة للتغيير ، سواء كنت (فئة أ) و المتصل (فئة ب) سوف تكون قادرة على تغيير أي قابلة للتغيير الدولة من الكائنات داخل المجموعة.

التطبيق الخاص بك يعتمد على الاحتياجات الخاصة بك:- إذا كنت لا تهتم حول الطالب (فئة ب) من رؤية أي تغييرات أخرى على جمع ثم يمكنك مجرد استنساخ جمع يد ، ووقف رعاية.- إذا كنت تحتاج بالتأكيد المتصل (فئة ب) لمعرفة التغييرات التي يتم إجراؤها على جمع و كنت أريد أن يكون هذا الموضوع آمنة, ثم لديك أكثر من مشكلة على يديك.احتمال واحد هو تنفيذ الخاص بك مؤشر الترابط-الآمن البديل ReadOnlyCollection للسماح تأمين الوصول ، على الرغم من أن هذا سيكون غير تافهة وغير performant إذا كنت ترغب في دعم IEnumerable ، لا يزال لن يحميك ضد قابلة للتغيير العناصر في المجموعة.

ينبغي ملاحظة أنه في أكو's الجواب فقط حماية قائمة قراءتها فقط.العناصر في القائمة لا تزال جدا للكتابة.أنا لا أعرف إذا كان هناك أي طريقة حماية غير الذرية العناصر دون استنساخ لهم قبل وضعها في قراءة قائمة فقط.

كنت ترغب في استخدام العائد الكلمات الرئيسية.الحلقة من خلال IEnumerable قائمة والعودة النتائج مع وديعة.هذا يسمح للمستهلك استخدام كل دون تعديل المجموعة.

سوف ننظر بشيء من هذا القبيل:

List<string> _Data;
public IEnumerable<string> Data
{
  get
  {
    foreach(string item in _Data)
    {
      return yield item;
    }
  }
}

يمكنك استخدام نسخة من مجموعة بدلا من ذلك.

public IList<string> Data {
get {
    return new List<T>(data);
}}

بهذه الطريقة لا يهم إذا كان يحصل على تحديث.

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