متى يتم استخدام الفئات الثابتة في C# [نسخة مكررة]

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

  •  04-07-2019
  •  | 
  •  

سؤال

هذا السؤال لديه بالفعل إجابة هنا:

هذا ما MSDN يجب أن يقول تحت متى تستخدم الفئات الثابتة:

static class CompanyInfo
{
    public static string GetCompanyName() { return "CompanyName"; }
    public static string GetCompanyAddress() { return "CompanyAddress"; }
    //...
}

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

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

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

المحلول

لقد كتبت أفكاري حول الفئات الثابتة في إجابة Stack Overflow السابقة:الفصل باستخدام طريقة واحدة - أفضل نهج؟

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

تعدد الأشكال

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

مشاكل الواجهة

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

اختبارات

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

يعزز النقط

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

زحف المعلمة

في البداية، قد تتطلب هذه الطريقة الثابتة اللطيفة والبريئة معلمة واحدة.مع نمو الوظائف، تتم إضافة اثنين من المعلمات الجديدة.وسرعان ما تتم إضافة المزيد من المعلمات الاختيارية، لذلك نقوم بإنشاء حمولات زائدة للطريقة (أو فقط نضيف قيمًا افتراضية باللغات التي تدعمها).ولم يمض وقت طويل حتى أصبح لدينا طريقة تأخذ 10 معلمات.فقط الثلاثة الأولى مطلوبة بالفعل، المعلمات 4-7 اختيارية.ولكن إذا تم تحديد المعلمة 6، فيجب ملء 7-9 أيضًا...لو قمنا بإنشاء فئة لغرض واحد هو القيام بما فعلته هذه الطريقة الثابتة، فيمكننا حل هذه المشكلة عن طريق أخذ المعلمات المطلوبة في المنشئ، والسماح للمستخدم بتعيين قيم اختيارية من خلال الخصائص، أو الأساليب لتعيين قيم مترابطة متعددة في نفس الوقت.وأيضًا، إذا تطورت إحدى الطرق إلى هذا القدر من التعقيد، فمن المرجح أنها تحتاج إلى أن تكون في فئتها الخاصة على أي حال.

مطالبة المستهلكين بإنشاء مثيل للفصول دون سبب

إحدى الحجج الأكثر شيوعًا هي:لماذا نطالب المستهلكين من صفنا بإنشاء مثيل لاستدعاء هذه الطريقة الفردية، في حين لا فائدة من هذا المثيل بعد ذلك؟يعد إنشاء مثيل لفئة عملية رخيصة جدًا في معظم اللغات، لذا فإن السرعة ليست مشكلة.تعد إضافة سطر إضافي من التعليمات البرمجية إلى المستهلك تكلفة منخفضة لوضع الأساس لحل أكثر قابلية للصيانة في المستقبل.وأخيرًا، إذا كنت تريد تجنب إنشاء مثيلات، فما عليك سوى إنشاء غلاف فردي لفصلك يسمح بإعادة الاستخدام بسهولة - على الرغم من أن هذا يتطلب أن يكون فصلك عديم الحالة.إذا لم يكن عديم الحالة، فلا يزال بإمكانك إنشاء أساليب مجمعة ثابتة تتعامل مع كل شيء، بينما لا تزال تمنحك جميع المزايا على المدى الطويل.أخيرًا، يمكنك أيضًا إنشاء فصل دراسي يخفي إنشاء مثيل كما لو كان مفردًا:MyWrapper.Instance هي خاصية تُرجع للتو new MyClass();

فقط السيث يتعامل بشكل مطلق

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

معايير، معايير، معايير!

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

نصائح أخرى

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

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

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

تواصل مع OOP بداخلك ولن تخطئ أبدًا!

بالنسبة لـ C# 3.0، قد تكون طرق الامتداد موجودة فقط في الفئات الثابتة ذات المستوى الأعلى.

إذا كنت تستخدم أدوات تحليل التعليمات البرمجية (على سبيل المثال. FxCop)، سيوصي بوضع علامة على الطريقة static إذا لم تتمكن هذه الطريقة من الوصول إلى بيانات المثيل.الأساس المنطقي هو أن هناك مكاسب في الأداء. شبكة MSDN:CA1822 - وضع علامة على الأعضاء على أنهم ثابتون.

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

أنا أميل إلى استخدام الفئات الثابتة للمصانع.على سبيل المثال، هذه هي فئة التسجيل في أحد مشاريعي:

public static class Log
{
   private static readonly ILoggerFactory _loggerFactory =
      IoC.Resolve<ILoggerFactory>();

   public static ILogger For<T>(T instance)
   {
      return For(typeof(T));
   }

   public static ILogger For(Type type)
   {
      return _loggerFactory.GetLoggerFor(type);
   }
}

ربما لاحظت أيضًا أنه يتم استدعاء IoC باستخدام موصل ثابت. معظم بالنسبة لي، إذا كان بإمكانك استدعاء الأساليب الثابتة في الفصل الدراسي، فهذا كل ما يمكنك فعله، لذا أضع علامة على الفصل على أنه ثابت لمزيد من الوضوح.

الفئات الثابتة مفيدة جدًا ولها مكان، على سبيل المثال المكتبات.

أفضل مثال يمكنني تقديمه هو فئة .Net Math، وهي فئة ثابتة لمساحة اسم النظام تحتوي على مكتبة لوظائف الرياضيات.

إنه مثل أي شيء آخر، استخدم الأداة المناسبة للمهمة، وإذا لم يكن هناك أي شيء يمكن إساءة استخدامه.

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

يحتوي C#.Net على عدد من الفئات الثابتة التي يتم استخدامها تمامًا مثل فئة Math.

لذلك، بالنظر إلى التنفيذ الصحيح، فهي مفيدة للغاية.

لدينا فئة TimeZone ثابتة تحتوي على عدد من وظائف المنطقة الزمنية المتعلقة بالأعمال، وليست هناك حاجة لإنشاء مثيلات متعددة للفئة تمامًا مثل فئة Math التي تحتوي على مجموعة من الوظائف (الطرق) المرتبطة بالمنطقة الزمنية التي يمكن الوصول إليها عالميًا في فئة ثابتة .

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

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

بالطبع لا يزال هناك اعتماد مباشر على الطريقة الثابتة عادة الشر (هناك بعض الاستخدامات غير الشريرة).

أستخدم الفئات الثابتة كوسيلة لتحديد "الوظائف الإضافية" التي يمكن أن يستخدمها كائن من نوع معين ضمن سياق معين.عادة ما يتبين أنها فئات فائدة.

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

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

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

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

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

أنا أستخدم الفئات الثابتة فقط للأساليب المساعدة، ولكن مع ظهور الإصدار C# 3.0، أفضل استخدام أساليب الامتداد لتلك الأساليب.

نادرًا ما أستخدم أساليب الفئات الثابتة لنفس الأسباب التي تجعلني نادرًا ما أستخدم "نمط التصميم" المفرد.

مرتكز على MSDN:

  1. لا يمكنك إنشاء المثيل للفئات الثابتة
  2. إذا تم تعريف الفئة على أنها ثابتة، فيجب أن يكون متغير العضو ثابتًا لتلك الفئة
  3. مختوم [لا يمكن توريثه]
  4. لا يمكن أن يحتوي على مُنشئ المثيل
  5. إدارة الذاكرة

مثال:الحسابات الرياضية (قيم الرياضيات) لا تتغير [الحساب القياسي للقيم المحددة]

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