اقتراحات أراد مع قوائم التعداد T عندما وراثة من عامة الطبقات

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

  •  09-06-2019
  •  | 
  •  

سؤال

وأنا أعلم أن الإجابة لن تكون بسيطة ، وأنا بالفعل استخدام زوجين من (أعتقد القبيح) cludges.أنا ببساطة تبحث عن بعض أنيقة إجابات.

خلاصة الدرجة:

public interface IOtherObjects;

public abstract class MyObjects<T> where T : IOtherObjects
{
   ...

   public List<T> ToList()
   {
       ...
   }
}

الأطفال:

public class MyObjectsA : MyObjects<OtherObjectA> //(where OtherObjectA implements IOtherObjects)
{


}

public class MyObjectsB : MyObjects<OtherObjectB> //(where OtherObjectB implements IOtherObjects)
{


}

هل من الممكن تنفيذ الحلقات خلال مجموعة من MyObjects (أو أخرى مماثلة تجمع عامة أو غير ذلك) إلى الاستفادة من ثم إلى ToList طريقة MyObjects الفئة الأساسية, كما أننا لا تعرف على وجه التحديد نوع T في هذه المرحلة.

تحرير أما عن أمثلة محددة ، كلما يأتي, لقد فكرت في ذلك لفترة من الوقت ، فعلت شيئا مختلفا بدلا من ذلك ، لذا لا توجد حاليا أية متطلبات.ولكن كما يأتي جدا وكثيرا ما فكرت في أن تطفو عليه.

تحرير @سارة ليس نوع معين من جمع يهمني, أنها يمكن أن تكون قائمة ، ولكن لا يزال ToList طريقة كل حالة نسبيا غير صالحة للاستعمال ، دون مجهول نوع)

@أكو, حقيقية, و هذا السؤال قد يكون نسبيا افتراضية ، ومع ذلك يجري قادرة على استرداد ، والعمل مع قائمة T من الكائنات ، مع العلم فقط قاعدتهم نوع من المفيد جدا.وجود ToList عودته قائمة BaseType كان واحدا من الحلول

تحرير @ جميع:حتى الآن, وقد كان هذا النوع من النقاش كنت آمل ، على الرغم من أنه إلى حد كبير يؤكد كل ما يشتبه.شكرا جميعا حتى الآن ، ولكن أي شخص آخر, لا تتردد في المدخلات.

تحرير@روب نعم يعمل على تحديد نوع, ولكن ليس عندما يكون النوع الوحيد المعروف قائمة IOtherObjects.

@روب مرة أخرى شكراالتي عادة ما كانت cludgy الحل (لا تحزن :) ).إما هذا أو باستخدام ConvertAll وظيفة إلى مسبل من خلال مندوب.شكرا لأخذ الوقت لفهم المشكلة.

تصفيات تحرير في حال كنت مربكة قليلا

أن تكون أكثر دقة ، (كنت قد اسمحوا لي أحدث تنفيذ هذا الأمر معقد جدا):

دعونا نقول لدي 2 أنواع الكائنات ، ب ، ج وراثة من وجوه A.

العديد من السيناريوهات التي عرضت نفسها حيث من قائمة ب أو ج ، أو في حالات أخرى قائمة إما - ولكن أنا لا أعرف إذا أنا في الفئة الأساسية, أنا في حاجة إلى أقل من قائمة محددة من A.

المثال أعلاه كانت مخففة مثال قائمة أقل تحديدا ، المشكلة هو أحدث تجسيد.

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

@روب مرة أخرى و سارة

شكرا ولكن أنا لا أشعر أنني أفهم الأدوية في جميع ساكنة contexted المجد ، ولم نفهم المسائل في اللعب هنا.

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

بلدي نفور ما يطلق عليه cludge إلى حد كبير أننا بحاجة إلى القيام حلقة خلال مجموعة السجلات ببساطة تحويل الأشياء إلى القيمة الأساسية التي قد يكون ضرب الأداء.

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

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

المحلول

إذا كان لديك

class B : A
class C : A

وكان لديك

List<B> listB;
List<C> listC;

التي ترغب في علاج قائمة من نوع الأم

ثم يجب عليك استخدام

List<A> listA = listB.Cast<A>().Concat(listC.Cast<A>()).ToList()

نصائح أخرى

لماذا لديك مجموعة من MyObjects?هل هناك سبب معين لم يكن لديك قائمة ؟

في حالة MyObjectsA و MyObjectsB لا يكون المشتركة السلف.فئة عامة هو قالب مختلفة فصول لا قاعدة مشتركة الدرجة.إذا كنت تريد أن يكون لها خصائص مشتركة في فئات مختلفة استخدام الواجهات.لا يمكنك الاتصال ToList في حلقة قضية مختلفة التوقيع في فئات مختلفة.يمكنك إنشاء ToList أن يعود الكائنات بدلا من نوع معين.

يمكنك لا يزال من المحتمل الوصول إلى ToList (طريقة) ، ولكن منذ كنت غير متأكد من نوع ، لن هذا العمل ؟

foreach(var myObject in myObjectsList)
    foreach(var obj in myObject.ToList())
        //do something

بالطبع هذا سوف تعمل فقط على C# 3.0.

لاحظ أن استخدام فار هو مجرد إزالة شرط معرفة ما هو نوع قوائم تحتوي على ؛ بدلا من فرانك التعليقات التي لدي أوهام أن فار سوف تجعل الكتابة ديناميكية.

حسنا, أنا في حيرة التعليمات البرمجية التالي يعمل بشكل جيد بالنسبة لي (الفضول حصلت على أفضل مني!):

// Original Code Snipped for Brevity - See Edit History if Req'd

أو هل فاتني شيء ؟

تحديث الاستجابة التالية من العملية

طيب الآن أنا حقا في حيرة من أمره..ما تقوله هو أن كنت ترغب في الحصول على قائمة من كتبته القيم من عام/مجردة قائمة ؟ (الطبقات الطفل وبالتالي تصبح غير ذات صلة).

لا يمكنك العودة كتبته قائمة إذا أنواع الأطفال/واجهة على منفذي - أنها لا تتطابق!بالطبع يمكنك الحصول على قائمة من البنود التي هي من نوع معين من مجردة قائمة مثل ذلك:

    public List<OfType> TypedList<OfType>() where OfType : IOtherObjects
    {
        List<OfType> rtn = new List<OfType>();

        foreach (IOtherObjects o in _objects)
        {
            Type objType = o.GetType();
            Type reqType = typeof(OfType);

            if (objType == reqType)
                rtn.Add((OfType)o);
        }

        return rtn;
    }

إذا أنا لا يزال خارج قاعدة هنا يمكنك يرجى إعادة صياغة السؤال؟!(لا يبدو مثل أنا الوحيد غير متأكد من ما كنت في القيادة).أنا أحاول تحديد ما إذا كان هناك سوء فهم من الأدوية على الجزء الخاص بك.

آخر تحديث :D

صحيح, لذلك يبدو أنك تريد/تحتاج خيار الحصول على كتابة أو قائمة أو قاعدة قائمة ؟

هذا من شأنه أن يجعل فئة مجردة تبدو مثل هذا - يمكنك استخدام ToList للحصول على الخرسانة أو نوع ToBaseList() للحصول على قائمة من نوع الواجهة.هذا يجب أن تعمل في أي سيناريوهات لديك.هل هذا يساعد ؟

public abstract class MyObjects<T> where T : IOtherObjects
{
    List<T> _objects = new List<T>();

    public List<T> ToList()
    {
        return _objects;
    }

    public List<IOtherObjects> ToBaseList()
    {
        List<IOtherObjects> rtn = new List<IOtherObjects>();
        foreach (IOtherObjects o in _objects)
        {
            rtn.Add(o);
        }
        return rtn;
    }
}

تحديث #3

انها ليست حقا "cludgy" الحل (لا تحزن اتخذت) إنها الطريقة الوحيدة للقيام بذلك..أعتقد أن المشكلة الأكبر هنا هو تصميم/جروك المشكلة.قلت أن لديك مشكلة ، هذا الرمز يحل.ولكن إذا كنت تتوقع أن تفعل شيئا مثل:

public abstract class MyObjects<T> where T : IOtherObjects
{
    List<T> _objects = new List<T>();

    public List<IOtherObjects> Objects
    { get { return _objects; } }
}
#warning This won't compile, its for demo's sake.

و تكون قادرة على انتقاء و اختيار الأنواع التي تخرج منه ، وإلا كيف يمكن أن يمكنك أن تفعل ذلك؟!أشعر أنك لا أفهم حقا ما الفائدة من الأدوية و تحاول الحصول عليها أن تفعل شيئا فهي ليست مصممة!?

لقد وجدت في الآونة الأخيرة

List<A>.Cast<B>().ToList<B>()

نمط.

يفعل بالضبط ما كنت أبحث عنه ،

الأدوية المستخدمة ساكنة الوقت نوع الشيكات لا وقت الإرسال.استخدام الميراث/واجهات وقت الإرسال ، استخدام الأدوية من أجل تجميع الوقت نوع من الضمانات.

interface IMyObjects : IEnumerable<IOtherObjects> {}
abstract class MyObjects<T> : IMyObjects where T : IOtherObjects {}

IEnumerable<IMyObjects> objs = ...;
foreach (IMyObjects mo in objs) {
    foreach (IOtherObjects oo in mo) {
        Console.WriteLine(oo);
    }
}

(من الواضح أنني أفضل Enumerables على القوائم.)

أو مجرد استخدام السليم لغة ديناميكية مثل VB.:-)

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