سؤال

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

function ReturnTwoStrings (out Str1 : String) : String;
begin
  ExecuteProcedure (procedure
                    begin
                      Str1 := 'First String';
                      Result := 'Second String';
                    end);
end;

جدا الاصطناعي سبيل المثال بالطبع ولكنني واجهت بعض الحالات التي قد يكون من المفيد.

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

تحرير أنا فقط أدركت أنه يعمل على المعايير العادية مثل

... (List : TList)

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

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

المحلول

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

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

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

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

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

الوضع مختلف مع المعلمات التي تم تمريرها من قبل المرجعية لأن التوقعات المتصل مختلفة.مبرمج للقيام بذلك:

procedure GetSomeString(out s: string);
// ...
GetSomeString(s);

سيكون مندهش للغاية إذا GetSomeString أن نضع إشارة إلى s متغير مرت في.من ناحية أخرى:

procedure AddObject(obj: TObject);
// ...
AddObject(TObject.Create);

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

نصائح أخرى

المشكلة هي أن Str1 متغير لا "التي تملكها" ReturnTwoStrings, حتى أن طريقة مجهول لا يمكن القبض عليه.

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

تحرير: (تضاف بعد تعليق من الجذاب)

جوهر مجهول الأساليب أنها التقاط المتغيرات (لا قيمها).

ألين باور (CodeGear) يوضح أكثر قليلا عن متغير التقاط في بلوق.

هناك C# سؤال حول التحايل على المشكلة وكذلك.

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

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

أنا أضع هذا في إجابة منفصلة لأن تحرير الخاص بك يجعل مسألة مختلفة حقا.

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

تحرير الخاص بك يشير إلى أنك بحاجة إلى إعادة التفكير حول أنواع القيم ، مرجع أنواع تأثير فار ، ، const و لا المعلمة العلامات على الإطلاق.

دعونا نفعل أنواع قيمة الشيء الأول.

القيم من قيمة الأنواع الحية على كومة لديك نسخة على التنازل السلوك.(سأحاول أن تشمل مثال على ذلك لاحقا).

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

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

القيم المرجعية أنواع تعيش على كومة ، لذلك بالنسبة لهم لا يهم إذا كان لديك ، فار ، const أو أي معلمة بمناسبة:عند تغيير شيء ما ، يمكنك تغيير القيمة في كومة الذاكرة المؤقتة.

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

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

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

الذي هو دائما مشكلة مع الإشارة المعلمات, لا يهم إذا كنت تستخدم طرق مجهولة أو لا.

فعلى سبيل المثال هذا:

procedure TMyClass.AddObject(Value: TObject);
begin
  FValue := Value;
end;

procedure TMyClass.DoSomething();
begin
  ShowMessage(FValue.ToString());
end;

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

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

حتى مع تحرير سؤالك يغير في الواقع من طرق مجهولة إلى الآثار المترتبة على استخدام إشارة كتبته المعلمات عمر الإدارة العامة.

نأمل جوابي يساعدك على الذهاب في هذا المجال.

--يروين

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