المنطق وتطبيقه على المجموعات.العامة والميراث

StackOverflow https://stackoverflow.com/questions/110121

  •  02-07-2019
  •  | 
  •  

سؤال

كل شيء يرث من الكائن.فهو أساس الميراث.كل شيء يمكن أن يلقي ضمنا شجرة الميراث، أي.

object me = new Person();

وبالتالي، بعد ذلك حتى نهايته المنطقية، ستكون مجموعة الأشخاص أيضًا مجموعة من الأشياء:

List<Person> people = new List<Person>();
people.Add(me);
people.Add(you);
List<object> things = people; // Ooops.

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

السؤال هو هذا:هل هناك سبب لهذا السلوك؟هل هناك حل أبسط للحصول على السلوك المطلوب؟

للتسجيل، أعتقد أن الموقف الذي أردت فيه هذا النوع من السلوك كان وظيفة طباعة عامة تعرض قوائم الكائنات عن طريق استدعاء ToString() وتنسيق السلاسل بشكل جيد.

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

المحلول

حسنًا، كل من استخدم الأدوية الجنيسة في .net لا بد أن يكون قد واجه هذا الأمر في وقت أو آخر.

نعم، بشكل حدسي يجب أن تعمل.لا، في الإصدار الحالي من برنامج التحويل البرمجي C# لا يحدث ذلك.

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

يحرر:

استخرجت رابطًا آخر ذي صلة، وهذا الرابط يناقش كيفية تعامل جافا مع هذا.يرى هنا

نصائح أخرى

يمكنك استخدام linq لإلقاءه:

IEnumerable<Person> oldList = someIenumarable;
IEnumerable<object> newList = oldlist.Cast<object>()

للوهلة الأولى، هذا ليس منطقيا بديهيا.لكنها تفعل ذلك.أنظر إلى هذا الكود:

List<Person> people = new List<Person>();
List<object> things = people; // this is not allowed
// ...
Mouse gerald = new Mouse();
things.add(gerald);

الآن لدينا فجأة List ل Person أشياء...مع Mouse داخله!

وهذا ما يفسر سبب تعيين كائن من النوع A<T> لمتغير من النوع A<S> لا يجوز، ولو S هو نوع فائق من T.

الحل البديل linq هو حل جيد.الحل البديل الآخر، نظرًا لأنك تستخدم كائن الكتابة، هو تمرير القائمة كـ IEnumerable (وليس الإصدار العام).

يحرر:يدعم الإصدار C# 4 (الإصدار التجريبي حاليًا) معلمة النوع المتغير في IEnumerable.على الرغم من أنك لن تتمكن من التعيين مباشرة إلى قائمة <object>، يمكنك تمرير قائمتك إلى طريقة تتوقع IEnumerable<object>.

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

للحصول على شرح مفصل لهذا، يجب أن يكون فيديو Channel9 التالي مفيدًا:

http://channel9.msdn.com/shows/Going+Deep/Inside-C-40-dynamic-type-اختياري-parameters-more-COM-Friendly/

مع طرق تمديد linq يمكنك القيام بذلك

IEnumerable<object> things = people.Cast<object>();
List<object> things = people.Cast<object>().ToList();

بخلاف ذلك، نظرًا لأنك تكتب القائمة بقوة، فلن يُسمح بالتحويل الضمني.

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