كيفية استخدام طريقة إخفاء (جديد) مع فئة مقيدة عامة

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

  •  27-09-2019
  •  | 
  •  

سؤال

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

من الواضح أنني أسيء فهم شيء أساسي هنا. اعتقدت أن العام where T: xxx كان قيدًا ، وليس نوعًا من البث.

يوضح هذا الرمز العينة بشكل أساسي ما أتحدث عنه.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GenericPartialTest
{
    class ContextBase
    {
        public string GetValue()
        {
            return "I am Context Base: " + this.GetType().Name;
        }

        public string GetOtherValue()
        {
            return "I am Context Base: " + this.GetType().Name;
        }

    }

    partial class ContextSub : ContextBase
    {
        public new string GetValue()
        {
            return "I am Context Sub: " + this.GetType().Name;
        }
    }

    partial class ContextSub
    {
        public new string GetOtherValue()
        {
            return "I am Context Sub: " + this.GetType().Name;
        }
    }

    class Container<T> where T: ContextBase, new()
    {
        private T _context = new T();

        public string GetValue()
        {
            return this._context.GetValue();
        }

        public string GetOtherValue()
        {
            return this._context.GetOtherValue();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Simple");
            ContextBase myBase = new ContextBase();
            ContextSub mySub = new ContextSub();

            Console.WriteLine(myBase.GetValue());
            Console.WriteLine(myBase.GetOtherValue());
            Console.WriteLine(mySub.GetValue());
            Console.WriteLine(mySub.GetOtherValue());

            Console.WriteLine("Generic Container");
            Container<ContextBase> myContainerBase = new Container<ContextBase>();
            Container<ContextSub> myContainerSub = new Container<ContextSub>();

            Console.WriteLine(myContainerBase.GetValue());
            Console.WriteLine(myContainerBase.GetOtherValue());
            Console.WriteLine(myContainerSub.GetValue());
            Console.WriteLine(myContainerSub.GetOtherValue());


            Console.ReadKey();
        }
    }
}

تعديل:

أعتقد أن ارتباك يأتي من ذلك يمكن للمرء أن يفعل هذا

class SomeClass<T> where T: AnotherType, new()
{
    T foo = new T();     
}

وتوقعت T ان نكون T على الرغم من أنني أفهم أن المترجم سوف ينظر إليه T كما كان كذا AnotherTypeواجهة. لقد افترضت كتابة T سيحدث في وقت التشغيل حتى لو كانت واجهة T تم تعيينه في وقت الترجمة. ال T foo يبدو الإعلان مضللاً هنا لأنه يفعل حقًا

AnotherType foo = new T();

بمجرد أن أفهم أنه لا يعلن حقًا foo كنوع T, ، من المفهوم لماذا new طريقة الاختباء لن تعمل.

وهذا كل ما يجب أن أقوله عن ذلك.

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

المحلول

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

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

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

هناك طريقتان محتملتان لكي تترك حول هذه المسألة:

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

نصائح أخرى

أظن هذا السؤال جدا سألت قد تساعدك. انظر إجابة جون سكيت هناك لسبب عدم إمكانية ذلك.

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

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