الاستخدامات العملية ل "الداخلية" الكلمات الرئيسية في C#

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

  •  03-07-2019
  •  | 
  •  

سؤال

هل يمكن شرح ما الاستخدام العملي هو internal الكلمة الرئيسية في C# ؟

وأنا أعلم أن internal التعديل يحد من الوصول إلى الجمعية الحالية ، ولكن متى وفي أي ظرف من الظروف يجب أن استخدمه ؟

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

المحلول

والمساعدة أو المساعد الطبقات / الأساليب التي كنت ترغب في الوصول إليه من العديد من الفئات الأخرى ضمن نفس التجمع، ولكن ان كنت تريد التأكد من التعليمات البرمجية في التجمعات الأخرى لا يمكن الوصول إليها.

من <لأ href = "https://web.archive.org/web/20130305112130/http://msdn.microsoft.com/en-us/library/7c5ka91b(v=vs.80).aspx" يختلط = "noreferrer"> MSDN (عبر archive.org):

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

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

ويمكنك أيضا استخدام المعدل الداخلي جنبا إلى جنب مع السمة مستوى التجميع InternalsVisibleTo لخلق تجمعات "صديق" التي يتم منحها وصول خاص إلى الطبقات الداخلية التجميع الهدف.

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

نصائح أخرى

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

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

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

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

إذا كنت تكتب DLL التي بتغليف طن من الوظائف المعقدة في API العامة بسيط، ثم "الداخلية" يستخدم على أعضاء الفئة التي ليست أن تتعرض علنا.

وإخفاء تعقيد (المعروف أيضا باسم التغليف) هو رئيس مفهوم هندسة البرمجيات الجودة.

ويستخدم الكلمة الداخلية بشكل كبير عند بناء المجمع على غير التعليمات البرمجية المدارة.

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

ويمكنك إلقاء نظرة على Mono.Cairo، انها التفاف حول مكتبة القاهرة التي تستخدم هذا النهج.

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

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

وأجد الداخلية أن يبالغ بكثير. كنت حقا لا ينبغي تعريض functionailty معينة فقط لبعض الفئات التي لن للمستهلكين آخرين.

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

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

وثمة مشكلة أخرى هي أن الكثير من المطورين و<م> يعتقد قد يحتاجون لاستخدامها في أي مكان آخر في التجمع وعلامة على أنها داخلية على أي حال، على الرغم من أنها لا تحتاج في ذلك الوقت. مطور آخر ثم قد يظن بها هناك لاتخاذ. عادة تريد وضع علامة الخاص حتى يكون لديك حاجة definative.

ولكن بعض من هذا يمكن أن يكون شخصي، وأنا لا أقول أنه لا ينبغي أبدا أن تستخدم. مجرد استخدام عند الحاجة.

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

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

namespace Base.Assembly
{
  public abstract class Parent
  {
    internal abstract void SomeMethod();
  }

  //This works just fine since it's in the same assembly.
  public class ChildWithin : Parent
  {
    internal override void SomeMethod()
    {
    }
  }
}

namespace Another.Assembly
{
  //Kaboom, because you can't override an internal method
  public class ChildOutside : Parent
  {
  }

  public class Test 
  { 

    //Just fine
    private Parent _parent;

    public Test()
    {
      //Still fine
      _parent = new ChildWithin();
    }
  }
}

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

هذا المثال يحتوي على ملفين:Assembly1.cs Assembly2.cs.الملف الأول يحتوي على داخلية قاعدة الطبقة ، BaseClass.في الملف الثاني محاولة إنشاء مثيل BaseClass سوف ينتج خطأ.

// Assembly1.cs
// compile with: /target:library
internal class BaseClass 
{
   public static int intM = 0;
}

// Assembly1_a.cs
// compile with: /reference:Assembly1.dll
class TestAccess 
{
   static void Main()
   {  
      BaseClass myBase = new BaseClass();   // CS0122
   }
}

في هذا المثال ، استخدام نفس الملفات المستخدمة في المثال 1 ، وتغيير الوصول إلى مستوى BaseClass إلى العامة.أيضا تغيير مستوى الوصول من الأعضاء IntM إلى الداخلية.في هذه الحالة ، يمكنك إنشاء مثيل فئة, ولكن لا يمكنك الوصول إلى الأعضاء الداخلية.

// Assembly2.cs
// compile with: /target:library
public class BaseClass 
{
   internal static int intM = 0;
}

// Assembly2_a.cs
// compile with: /reference:Assembly1.dll
public class TestAccess 
{
   static void Main() 
   {      
      BaseClass myBase = new BaseClass();   // Ok.
      BaseClass.intM = 444;    // CS0117
   }
}

المصدر: http://msdn.microsoft.com/en-us/library/7c5ka91b(مقابل.80).aspx

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

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

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

وعندما يكون لديك طرق، والطبقات، وغيرها التي تحتاج إلى أن تكون في متناول ضمن نطاق البرلمان الحالي وأبدا خارجها.

وعلى سبيل المثال، قد يكون DAL على ORM ولكن لا ينبغي أن يتعرض الكائنات إلى طبقة رجال الأعمال يجب أن تتم جميع التفاعل من خلال أساليب ثابتة ويمر في معلمتين المطلوبة.

كما سيادة الإبهام هناك نوعين من الأعضاء:

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

والحد من الضوضاء، وأنواع أقل لك فضح أكثر بساطة مكتبتك. عبث التدقيق / الأمن هو آخر (على الرغم من التأمل يمكن الفوز ضدها).

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

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

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

ولدي مشروع الذي يستخدم-LINQ إلى SQL للبيانات الخلفية. لقد اثنين من النطاقات الرئيسية: بيز والبيانات. يعيش نموذج البيانات LINQ في البيانات ويتم وضع علامة "الداخلية". مساحة الاسم بيز ديه الطبقات العامة التي التفاف حول الطبقات البيانات LINQ.

وهكذا هناك Data.Client، وBiz.Client. هذا الأخير يكشف عن الخصائص ذات الصلة كائن البيانات، منها مثلا:

private Data.Client _client;
public int Id { get { return _client.Id; } set { _client.Id = value; } }

والكائنات بيز لديها منشئ الخاص (لفرض استخدام أساليب المصنع)، ومنشئ الداخلي الذي يبدو مثل هذا:

internal Client(Data.Client client) {
    this._client = client;
}

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

وهذه هي المرة الأولى التي تستخدم حقا internal من ذلك بكثير، وانها تثبت مفيدة للغاية.

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

ولكن، لا أستطيع أن أرى أي نقطة في جعل فئات أو أفراد internal دون أسباب محددة، تماما كما قليلا كما أنه من المنطقي أن جعلها public، أو private دون أسباب محددة.

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

واستخدام واحدة من الكلمة الداخلية هو لتقييد الوصول إلى تطبيقات ملموسة من المستخدم من التجميع الخاص بك.

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

وبالإضافة إلى ذلك، تسمح المنشئات الداخلية لك التحكم أين ومتى تم إنشاء مثيل فئة غير ذلك العام.

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

والتعليقات هي موضع ترحيب حول هذا النهج.

ونضع في اعتبارنا أن أي فئة محددة كما public سوف تظهر تلقائيا في التحسس عندما ينظر شخص في مساحة المشروع. من وجهة نظر API، من المهم فقط للمستخدمين عرض المشروع الخاص بك الطبقات التي يمكن استخدامها. استخدم الكلمة internal لإخفاء الأشياء التي لا ينبغي أن نرى.

وإذا كان المقصود Big_Important_Class ل Project A للاستخدام خارج المشروع الخاص بك، ثم يجب أن لا علامة عليه internal.

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

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

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

الخ.

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

وعندما يكون لديك الطبقات أو الأساليب التي لا تناسب نظيفة في النموذج الشيئية، والتي تفعل أشياء خطيرة، والتي تحتاج ليتم استدعاؤها من الفئات وأساليب أخرى تحت سيطرتك، والتي لا ترغب في السماح أي شخص آخر استخدام.

public class DangerousClass {
    public void SafeMethod() { }
    internal void UpdateGlobalStateInSomeBizarreWay() { }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top