أفضل الممارسات للثابت مقابل.طرق المثيل عندما تكون القيم مطلوبة

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

سؤال

لقد قرأت عن ثابت مقابل.طرق المثيل هنا، لكنني لا أرى أيًا منها يجيب على هذا السؤال بالتحديد (الأخضر كما قد يكون).

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

أي.

class Foo
{
    //properties
    bar1;
    bar2;

    //method
    sumbar1andbar2()
    {
        return bar1 + bar2;
    }
}

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

Foo foo1 = new Foo();
foo1.bar1 = x;
foo1.bar2 = y;
sumbar1andbar2(foo1.bar1, foo1.bar2); 

ولكن على الرغم من أن طريقة المثيل أدناه تبدو أكثر نظافة، إلا أنني لست على علم بوجود طريقة نظيفة وسهلة للتأكد من أن كل من bar1 وbar2 ليسا فارغين، مما قد يتسبب في حدوث استثناء:

Foo foo1 = new Foo();
foo1.bar1 = x;
foo1.bar2 = y;
sumbar1andbar2();

ومع ذلك، يبدو أسلوب المثيل أفضل إذا قام الأسلوب بتعديل خاصية أخرى للفئة، مثل bar3.

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

المحلول

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

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

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

نصائح أخرى

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

إذا كانت عملية حسابية عامة (مثل مثالك) حيث قد ترغب في استخدامها في مكان آخر ، فلديك بعض الخيارات:

اجعلها طريقة ثابتة في فئة الأداة المساعدة ، على سبيل المثال

Genacodicetagpre

اجعلها أسلوب الامتداد على Foo ، إنها فئة الأصل ،أو واجهة تحدد x و y ، على سبيل المثال

Genacodicetagpre

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

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

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

الخصائص التي تتعلق بطبيعة الفئة بدلاً من مثيل معين يجب أن تكون ثابتة أيضًا لنفس السبب.على سبيل المثال int.MaxValue هي خاصية int, ، وليس على سبيل المثال.93.

لاحظ أن نتيجة int.MaxValue هو في حد ذاته int.هذا ليس من غير المألوف.وتشمل الأمثلة الأخرى TimeSpan.Zero و string.Empty.يمكن أن يكون هذا أمرًا مريحًا وأيضًا في بعض الأحيان فائدة أداء في منع الكثير من أنواع المراجع المكررة (غير ذات صلة في حالة أنواع القيم، ولا ينبغي المبالغة في ذكرها في حالة أنواع المراجع).من المهم عدم المبالغة في القيام بذلك.لا نريد تشغيل 4294967296 خصائص ثابتة مختلفة int لتسهيل الاتصال بهم!بشكل عام، يكون هذا مفيدًا عندما:

لا يمكن إنشاء الحالة الخاصة بواسطة المُنشئ.

أو:

يتم استخدام الحالة الخاصة بشكل شائع (TimeSpan.Zero) و/أو غير مناسب للتذكر (int.MaxValue هو أكثر وضوحا وأسهل للتذكر من 2147483647 او حتى 0x7FFFFFFF).خاصة إذا كان كلاهما بالطبع.

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

  1. لا يمكنك الوصول إلى مصدر الفصل (إنه فصل خاص بطرف آخر).
  2. تريد تعريفه على واجهة بدلاً من الفصل الدراسي.
  3. تريد أن تكون قابلة للاستدعاء عند القيمة null (تجنب ذلك، فهذا غير اصطلاحي في C# على الرغم من أنه أكثر شيوعًا في اللغات الأخرى).
  4. تريد تعريفه لحالات معينة من الأدوية العامة.على سبيل المثال، إذا خلقت MyDictionary<TKey, TValue> التي نفذت IDictionary<TKey, TValue> لا أستطيع تحديد أ plus طريقة تضيف رقمًا إلى قيمة مخزنة لأن ذلك لا يمكن أن يعمل إلا عندما يكون TValue نوعًا رقميًا معروفًا.يمكنني تعريف هذه الطريقة كطريقة تمديد مثل int Plus<TKey>(this MyDictionary<TKey, int> dict, int addend) والذي سيظهر بعد ذلك كعضو مثيل عندما TValue هو int، لكنه لن يتداخل مع استخدام MyDictionary لمعلمات نوع أخرى.

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

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