سؤال

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

في منشئ:

public Light(Vector v)
{
    this.dir = new Vector(v);
}

في مكان آخر

public void SomeMethod()
{
    Vector vec = new Vector();
    double d = (vec * vec) - (this.radius * this.radius);
}
هل كانت مفيدة؟

المحلول

هناك عدة استخدامات ل هذا الكلمة الأساسية في لغة C#.

  1. لتأهيل الأعضاء المخفيين بالاسم المماثل
  2. لجعل الكائن يمرر نفسه كمعلمة إلى طرق أخرى
  3. لجعل الكائن يعود بنفسه من إحدى الطرق
  4. للإعلان عن الفهارس
  5. للإعلان عن طرق التمديد
  6. لتمرير المعلمات بين المنشئين
  7. لإعادة تعيين قيمة نوع القيمة (البنية) داخليًا.
  8. لاستدعاء طريقة ملحق في المثيل الحالي
  9. ليلقي نفسه إلى نوع آخر
  10. لسلسلة المنشئين المحددين في نفس الفئة

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

نصائح أخرى

لا أقصد أن يبدو هذا غريبًا، لكن لا يهم.

بجد.

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

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

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

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

class Vector3
{
    float x;
    float y;
    float z;

    public Vector3(float x, float y, float z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }

}

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

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

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

لا أستطيع أن أصدق كل الأشخاص الذين يقولون إن استخدامه دائمًا هو "أفضل ممارسة" وما إلى ذلك.

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

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

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

أستخدمه كلما StyleCop يقول لي. StyleCop يجب أن يطيع.نعم بالتأكيد.

في أي وقت تحتاج إلى مرجع للكائن الحالي.

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

مثال:

void onChange()
{
    screen.draw(this);
}

أنا أميل إلى استخدامه في كل مكان أيضًا، فقط للتأكد من أنه من الواضح أننا نتعامل مع الأعضاء المثيلين.

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

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

class Example : ICloneable
{
    private void CallClone()
    {
        object clone = ((ICloneable)this).Clone();
    }

    object ICloneable.Clone()
    {
        throw new NotImplementedException();
    }
}

هنا عندما أستخدمه:

  • الوصول إلى الأساليب الخاصة من داخل الفصل (للتمييز)
  • تمرير الكائن الحالي إلى طريقة أخرى (أو ككائن مرسل، في حالة وقوع حدث)
  • عند إنشاء طرق التمديد :D

لا أستخدم هذا للحقول الخاصة لأنني أسبق أسماء متغيرات الحقول الخاصة بشرطة سفلية (_).

[ج++]

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

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

  • تمرير "نفسك" إلى وظيفة.
  • تعيين "نفسك" لمؤشر أو شيء من هذا القبيل.
  • صب، أي.الصب لأعلى/لأسفل (آمن أو غير ذلك)، والتخلص من الثبات، وما إلى ذلك.
  • المترجم فرض توضيح.

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

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

class AABB
{
  // ... members
  bool intersects( AABB other )
  {
    return other.left() < this->right() &&
           this->left() < other.right() &&

           // +y increases going down
           other.top() < this->bottom() &&
           this->top() < other.bottom() ;
  }
} ;

(ضد)

class AABB
{
  bool intersects( AABB other )
  {
    return other.left() < right() &&
           left() < other.right() &&

           // +y increases going down
           other.top() < bottom() &&
           top() < other.bottom() ;
  }
} ;

في لمحة سريعة عما تفعله AABB right() تشير إلى؟ال this يضيف قليلا من التوضيح.

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

class MyClass {
    private int _x
    public MyClass() : this(5) {}
    public MyClass(int v) { _x = v;}
}

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

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

لقد اعتدت على استخدامه بحرية في Visual C++ نظرًا لأن القيام بذلك سيؤدي إلى تشغيل IntelliSense، لقد قمت بالضغط على المفتاح ">"، وأنا كسول.(و عرضة للأخطاء المطبعية)

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

أميل إلى التأكيد على الحقول بـ _ لذلك لا أحتاج أبدًا إلى استخدام هذا.كما يميل R# إلى إعادة هيكلتها بعيدًا على أي حال ...

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

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

boolean sameValue (SomeNum other) {
   return this.importantValue == other.importantValue;
} 

[ج++]

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

A a;
a = a;

سيتم كتابة عامل المهمة الخاص بك:

A& A::operator=(const A& a) {
    if (this == &a) return *this;

    // we know both sides of the = operator are different, do something...

    return *this;
}

this على مترجم C++

سيبحث مترجم C++ بصمت عن الرمز إذا لم يعثر عليه على الفور.في بعض الأحيان يكون الأمر جيدًا في أغلب الأحيان:

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

ولكن احيانا، أنت فقط لا تريد أن يخمن المترجم.تريد من المترجم أن يلتقط الرمز الصحيح وليس رمزًا آخر.

لي, ، هذه هي الأوقات التي أرغب فيها، ضمن إحدى الطرق، في الوصول إلى طريقة عضو أو متغير عضو.أنا فقط لا أريد أن يتم التقاط بعض الرموز العشوائية لمجرد أنني كتبت printf بدلاً من print. this->printf لن يكون تجميعها.

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

هذه هي الأسباب التي أستخدمها this.

(§) لا يزال الأمر غامضًا بالنسبة لي، لكنني الآن أتساءل عما إذا كانت حقيقة تضمين رأس <windows.h> في مصدرك، هي السبب وراء تلويث جميع رموز مكتبات C القديمة لمساحة الاسم العالمية الخاصة بك

(§§) إدراك أنك "تحتاج إلى تضمين رأس، ولكن تضمين هذا الرأس سيؤدي إلى كسر التعليمات البرمجية الخاصة بك لأنه يستخدم بعض وحدات الماكرو الغبية مع اسم عام" هو أحد تلك الأشياء الروليت الروسية لحظات من حياة المبرمج

'هذا.' يساعد في العثور على الأعضاء في "هذا" الفئة مع الكثير من الأعضاء (عادةً ما يرجع إلى سلسلة الميراث العميق).

الضغط على CTRL+Space لا يساعد في ذلك، لأنه يشمل أيضًا الأنواع؛حيث "هذا". يشمل الأعضاء فقط.

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

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

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

أنا استخدامها للاستدعاء التحسس تماما مثل جون ماك جي, ، لكنني سأعود وأمحو "هذا->" عندما أنتهي.أتبع تقليد Microsoft المتمثل في بادئة متغيرات الأعضاء بـ "m_"، لذا فإن تركها كوثائق سيكون مجرد زائدة عن الحاجة.

1 - لغة واضعة Java الشائعة:

 public void setFoo(int foo) {
     this.foo = foo;
 }

2 - عند استدعاء دالة بهذا الكائن كمعلمة

notifier.addListener(this);

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

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

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

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

يمكنك استخدام this لتحويل اسم غير تابع إلى اسم تابع للوسيطة داخل فئات القالب التي ترث من القوالب الأخرى.

template <typename T>
struct base {
   void f() {}
};

template <typename T>
struct derived : public base<T>
{
   void test() {
      //f(); // [1] error
      base<T>::f(); // quite verbose if there is more than one argument, but valid
      this->f(); // f is now an argument dependent symbol
   }
}

يتم تجميع القوالب بآلية تمريرتين.أثناء المرور الأول، يتم حل وفحص الأسماء التابعة غير الوسيطة فقط، بينما يتم فحص الأسماء التابعة فقط من أجل التماسك، دون استبدال وسيطات القالب فعليًا.

في هذه الخطوة، دون استبدال النوع فعليًا، لا يكون لدى المترجم أي معلومات تقريبًا عن ماذا base<T> يمكن أن يكون (لاحظ أن تخصص القالب الأساسي يمكن أن يحوله إلى أنواع مختلفة تمامًا، حتى إلى أنواع غير محددة)، لذلك يفترض فقط أنه نوع.في هذه المرحلة الدعوة غير التابعة f الذي يبدو طبيعيًا بالنسبة للمبرمج هو رمز يجب على المترجم العثور عليه كعضو فيه derived أو في تضمين مساحات الأسماء - وهو ما لم يحدث في المثال - وسوف يشكو.

الحل هو تحويل الاسم غير التابع f إلى اسم تابع.يمكن القيام بذلك بطريقتين، من خلال الإشارة بوضوح إلى النوع الذي سيتم تنفيذه فيه (base<T>::f --إضافة base<T> يجعل الرمز يعتمد على T وسيفترض المترجم أنه سيكون موجودًا ويؤجل التحقق الفعلي للممر الثاني، بعد استبدال الوسيطة.

الطريقة الثانية، الكثير من أدوات الفرز إذا ورثت من القوالب التي تحتوي على أكثر من وسيطة واحدة، أو أسماء طويلة، هي مجرد إضافة this-> قبل الرمز.نظرًا لأن فئة القالب التي تقوم بتنفيذها تعتمد على وسيطة (فهي ترث من base<T>) this-> يعتمد على الوسيطة، ونحصل على نفس النتيجة: this->f يتم التحقق منه في الجولة الثانية، بعد استبدال معلمة القالب.

يجب ألا تستخدم "هذا" إلا إذا كان ذلك ضروريًا تمامًا.

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

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