الحروف والأدوات التي يتم تنفيذها تلقائيًا مقابل الحروف والأدوات التي يتم تنفيذها تلقائيًاالمجالات العامة

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

  •  02-07-2019
  •  | 
  •  

سؤال

أرى الكثير من الأمثلة البرمجية لفئات C# التي تقوم بذلك:

public class Point {
    public int x { get; set; }
    public int y { get; set; }
}

أو، في الكود الأقدم، نفس الشيء مع قيمة دعم خاصة صريحة وبدون الخصائص الجديدة التي يتم تنفيذها تلقائيًا:

public class Point {
    private int _x;
    private int _y;

    public int x {
        get { return _x; }
        set { _x = value; }
    }

    public int y {
        get { return _y; }
        set { _y = value; }
    }
}

سؤالي هو لماذا.هل هناك أي فرق وظيفي بين القيام بما سبق وجعل الحقول العامة لهؤلاء الأعضاء، كما هو موضح أدناه؟

public class Point {
    public int x;
    public int y;
}

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

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

المحلول

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

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

نصائح أخرى

من الأسهل أيضًا تغييره إلى هذا لاحقًا:

public int x { get; private set; }

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

الفكرة هي أنه حتى لو كانت بنية البيانات الأساسية بحاجة إلى التغيير، فلن يلزم تغيير الواجهة العامة للفصل.

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

Point pt = new Point();
if(Int32.TryParse(userInput, out pt.x))
{
     Console.WriteLine("x = {0}", pt.x);
     Console.WriteLine("x must be a public variable! Otherwise, this won't compile.");
}

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

يمكّنك Setter وGetter من إضافة طبقة تجريد إضافية وفي OOP النقي، يجب عليك دائمًا الوصول إلى الكائنات عبر الواجهة التي توفرها للعالم الخارجي ...

ضع في اعتبارك هذا الكود الذي سيوفر لك في asp.net والذي لن يكون ممكنًا بدون مستوى التجريد الذي توفره أدوات الضبط والحروف:

class SomeControl
{

private string _SomeProperty  ;
public string SomeProperty 
{
  if ( _SomeProperty == null ) 
   return (string)Session [ "SomeProperty" ] ;
 else 
   return _SomeProperty ; 
}
}

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

على سبيل المثال:

public string x { get; set; }

وعلى سبيل المثال، فإنك تستخدم بالفعل x كثيرًا من المرات ولا ترغب في كسر التعليمات البرمجية الخاصة بك.

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

فكرتي هي إضافة متغير خاص جديد وإضافة نفس x getter وsetter.

private string _x;

public string x { 
    get {return x}; 
    set {
        if (Datetime.TryParse(value)) {
            _x = value;
        }
    }; 
}

هل هذا ما تقصده بجعلها مرنة؟

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

يمكنك أيضًا وضع نقاط توقف على الحروف والمحددات، ولكن لا يمكنك ذلك في الحقول.

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

ربما مجرد جعل الحقول عامة يمكن أن يقودك إلى المزيد نموذج المجال فقر الدم.

أطيب التحيات

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

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

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

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

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

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

تعتبر أدوات Setters و getters سيئة من حيث المبدأ (إنها رائحة سيئة OO - سأتوقف عن القول إنها مضادة للنمط لأنها ضرورية حقًا في بعض الأحيان).

لا، لا يوجد فرق من الناحية الفنية، وعندما أرغب حقًا في مشاركة الوصول إلى كائن ما هذه الأيام، فإنني أحيانًا أجعله نهائيًا للعامة بدلاً من إضافة حرف getter.

الطريقة التي يتم بها "بيع" أدوات التثبيت والحاصلين هي أنك قد تحتاج إلى معرفة أن شخصًا ما يحصل على قيمة أو يغير قيمة ما - وهو أمر منطقي فقط مع البدائيين.

يتم استبعاد كائنات حقيبة الخصائص مثل DAOs وDTO وكائنات العرض من هذه القاعدة لأنها ليست كائنات في معنى "تصميم OO" الحقيقي لكلمة Object.(أنت لا تفكر في "تمرير الرسائل" إلى DAO، إنها مجرد كومة من أزواج السمات/القيمة).

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