قم بتعيين موصل C# للوصول إلى جميع الأنواع في التجميع، واحصل على مقيم فقط للأنواع المشتقة.كيف؟

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

سؤال

هذه الخاصية في نوع مع ممنوع الدخول المعدل (وبالتالي internal وصول):

class SomeType {
    private int length;
    internal int Length {
        get { return length; }
        set length = value; }
    }
}

يسمح لجميع الأنواع داخل تجميع SomeType للاستخدام get و set الملحقات. مشكلة:كيفية تقييد الوصول إلى set ل فقط الأنواع المشتقة من SomeType (و SomeType بالفعل)؟

internal int Length {
    get { return length; }
    protected set length = value; }
}

تم رفضه من قبل المترجم، لأن protected ويقال أنه أقل تقييدا ​​من internal (من المفترض: protected لديه تداخل مع internal, ، لكن هو غير متضمنة بالكامل في internal --> يمكن أن توجد الأنواع المشتقة خارج نطاق internal).

ماذا سيكون الرمز هل يمكن الوصول إليها بواسطة أي نوع داخل التجميع، وتعيينها فقط عن طريق الأنواع المشتقة داخل التجميع؟

يحرر:بعد مراجعة الإجابات، أعتقد أنني بحاجة إلى إضافة خاصية أخرى للخاصية، لأنها قد تُحدث فرقًا في الحل:نوع العقار هو في الواقع SomeType.الكود المعدل هو:

class SomeType {
    private SomeType length;
    internal SomeType Length {
        get { return length; }
        set length = value; }
    }
}

إذا تم الإعلان عن الممتلكات public, ، ثم يصدر المترجم خطأ (نوع الخاصية SomeType لا يمكن الوصول إليه بسهولة من خلال طول الخاصية).

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

المحلول

(يحرر:لقد قمت للتو بالتحقق، وهذا يعمل حتى عندما يكون نوع الخاصية هو نفس نوع الإعلان.ومع ذلك، فإنه لا العمل عندما تحاول الإعلان عن خاصية داخل ملف عام اكتب حيث نوع الخاصية هو داخلي يكتب.)

لا يمكنك فعل ذلك تمامًا في لغة C# (بالمعنى الدقيق للكلمة)، ولكن يمكنك القيام بشيء مشابه جدًا:

protected internal int Length { get; protected set; }

(هذا يستخدم خاصية يتم تنفيذها تلقائيًا من أجل البساطة فقط؛نفس التقنية ستعمل مع خاصية "عادية" أيضًا.)

وهذا سيجعل "getter" في متناول أي نوع داخل نفس التجميع و الأنواع المشتقة؛لن يكون "الواضع" متاحًا إلا للأنواع المشتقة.نظرًا لأن فصلك داخلي على أي حال، فهذا مكافئ إلى حد كبير على أي حال - سيكون المُحصل نظريًا متاحًا للأنواع خارج التجميع، ولكن نظرًا لأن الفصل داخلي، فلا ينبغي أن يُشتق أي شيء من تجميع مختلف من النوع الخاص بك على أي حال.

تكمن المشكلة في أن الخصائص تتطلب أن يكون أحد مستويات الوصول "مجموعة فرعية" من المستوى الآخر؛ internal و protected لا تعمل بهذه الطريقة - يمكن أن يكون هناك نوع واحد في نفس التجميع ولكنه غير مشتق من النوع المعني؛ويمكن استخلاص نوع آخر منه ولكن في تجميع مختلف.إنهم متعامدون، في الأساس.

الحل أعلاه يعمل بسبب protected internal يعني أنه في متناول أي نوع وهو أيضاً في نفس الجمعية أو مشتق من النوع.ومن الواضح أن كل من protected و internal بشكل فردي هو مجموعة فرعية من هذا.

أنت كان تكون قادرة على جعل internal الخاصية التي تم تقييدها بشكل أكبر بالنسبة إلى أداة الضبط إذا كان لدى C# ما يعادل عائلة CLR و مستوى الوصول إلى التجميع.(protected internal يعادل "العائلة". أو التجميع".) لسوء الحظ بالنسبة لك، لا :(

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

private int length;
internal int Length { get { return length; } }

protected void SetLength(int value)
{
    this.length = value;
}

نصائح أخرى

نظرًا لأن الفصل نفسه مرئي فقط في التجميع المُعلن (بسبب الخطأ الضمني internal معدّل الوصول)، ما عليك سوى إنشاء أداة الحصول على العقار public والواضع protected:

class SomeType {
    private int length;

    public int Length {
        get { return length; }
        protected set { length = value; }
    }
}

الحاصل سوف لن يمكن الوصول إليها خارج التجمع الخاص بك، حيث أن الفصل نفسه غير مرئي.


خارج الموضوع:إذا كان لديك مترجم C# حديث، فقد ترغب في استخدام الخصائص التلقائية بدلاً من ذلك:

class SomeType {
    public int Length { get; protected set; }
}

هذه خدعة لغة/مترجم فقط، لذلك لا يتعين عليك التجميع وفقًا لإطار عمل الإصدار 3.X للاستفادة منه.

ألا يمكنك قلبه (لم تختبره):

protected int Length
{
    internal get { return length; }
    set { length = value; }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top