سؤال

وكيف يمكنني اختيار طريقة جيدة (لدي في المثال تظهر أقل من 2 بمختلف الطريقة التي لا تعمل). كنت تستخدم بدلا من متغير من نوع الكائن مع IF وهو للقيام بهذه المهمة ولكن أحاول تجنب استخدام كائن والملاكمة / علبته. حتى ظننت أنه عام يمكن القيام بهذه المهمة ولكن أنا عالقة هنا.

وهنا مقتطف صغير من الشفرة التي توضح سؤالي:

class Program
{
    static void Main(string[] args)
    {
        Parser p = new Parser();
        ObjectType1 o1 = new ObjectType1();
        p.execute(o1);
        Console.Read();
    }
}

class Parser
{
    public T execute<T>(T obj)
    {
        /*
        if (obj is ObjectType1)
            this.action((ObjectType1)obj);
        else if (obj is ObjectType2)
            this.action((ObjectType2)obj);
        */
        this.action(obj);
        return obj;
    }

    private void action(ObjectType1 objectType1)
    {
        Console.WriteLine("1");
    }

    private void action(ObjectType2 objectType2)
    {
        Console.WriteLine("2");
    }
}


class ObjectType1
{
}

class ObjectType2
{
}

تحديث

وأنا لا أريد اجهة والطبقة. آسف. كنت أعرف أنه ليس الهدف من هذه المسألة.

والصب مع (ObjectType) الكائنات لا يعمل ولكن إذا قمت بذلك:

        if (obj is ObjectType1)
            this.action(obj as ObjectType1);
        else if (obj is ObjectType2)
            this.action(obj as ObjectType1);

ويعمل ... لماذا؟

و... لا أستطيع الزائد لجميع أنواع طريقة تنفيذ لأن هذا الأسلوب هو من واجهة. هذا هو السبب في كل حاجة ليتم استدعاؤها من هذا الأسلوب.

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

المحلول

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

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

using System;

class Test
{    
    static void Main()
    {
        string x = "hello";
        string y = string.Copy(x);

        Console.WriteLine(x==y); // Overload used
        Compare(x, y);
    }

    static void Compare<T>(T x, T y) where T : class
    {
        Console.WriteLine(x == y); // Reference comparison
    }
}

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

نصائح أخرى

هل تعتبر واجهات؟

interface IAction
{
   void action();
}

class ObjectType1 : IAction
{
   void action() {
      Console.WriteLine("1");
   }
}

class ObjectType2 : IAction
{
    void action() {
      Console.WriteLine("2");
    }
}

class Parser
{
   public IAction execute(IAction obj)
   {
      obj.action();
      return obj;
   }
}

بالتعديل OP:

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

<اقتباس فقرة>   

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

والمترجم وسوف نفعل هذا العمل بالنسبة لك. مجرد استخدام الزائدة.

class Parser
{
    public ObjectType1 action(ObjectType1 objectType1)
    {
        Console.WriteLine("1");
        return objectType1;
    }
    public ObjectType2 action(ObjectType2 objectType2)
    {
        Console.WriteLine("2");
        return objectType2;
    }
}

class ObjectType1 { }
struct ObjectType2 { }

وبعد ذلك، دعا مع:

Parser p = new Parser();
p.action(new ObjectType1());
p.action(new ObjectType2());

وليس هناك الملاكمة / علبته، ويحصل على استدعاء الأسلوب المناسب.

ولم أحاول ذلك، ولكن يمكنك أن تفعل هذا؟

<الإضراب>

<الإضراب>
public T execute<T>(T obj)
{
    this.action((T)obj);
    return obj;
}

<الإضراب>

(وفقا لتعليقات، لا يعمل)

أو

public T execute<T>(T obj)
{
    this.action(obj as T);
    return obj;
}

(وفقا لالتعليقات، يعمل)

وأنا أعلم أنك تشعر بالقلق إزاء الملاكمة / علبته، لذلك يمكن أن يكون هناك ValueTypes المعنية هنا.

public T execute<T>(T obj)   
{        
    this.action(obj);
    return obj;
}

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

والنظر في هذا الرمز:

    public int execute(int obj)   
    {        
        this.action(obj);
        return obj;
    }

    public void action(int obj)
    {
        obj = obj + 1;
    }

ودعا في هذا السبيل.

int x = p.execute(1);

وx هو 1، وليس 2.

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

والحمولة الزائدة حل كما هو الحال في أعمال الرد ديفيد B، ولكن يحدث أيضا أثناء وقت الترجمة.

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

وأشعر أنك تريد أن تتحول الطرق على أساس المدخلات وقت التشغيل.

هل يمكن الحصول على المزيد من السلوك الديناميكي إذا كنت تستخدم التأمل.

        public object execute(object obj) 
        {
            MethodInfo m = typeof(Parser).GetMethod(
                "action", 
                BindingFlags.Instance | BindingFlags.NonPublic, 
                null, 
                new Type[] { obj.GetType() }, 
                null);
            m.Invoke(this, new object[] { obj });
            return obj; 
        } 

وربما يكون هشا بعض الشيء، لكنه يعمل في المثال.

وIIRC يمكنك استخدام "حيث" شرط للسماح لهذا

public T execute<T>(T obj) where : /* somthing */
{
}

ولدي دائما إلى Google أن واحدا نفسي لذلك سأترك الامر عند هذا الحد.

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

Koodos إلى joshua.ewer من أجل العثور على الصفحة رجل

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