يناقش هذا التمرين بعض التفاصيل المتعلقة بمعاملات الطريقة واستخدامها في C#.
تنقل المعاملات معلومات من طريقة مستدعية إلى طريقة مستدعاة.
يمكن تعديل سلوك المعاملات باستخدام معدِّلات مثل ref و out.
ينقل المعامل المزوَّد بالمعدِّل out قيمةً عائدةً من الطريقة المستدعاة إلى المستدعي. يمكن تمرير المعامل إلى الطريقة المستدعاة دون تهيئته، وفي كل الأحوال يُعامَل داخل الطريقة المستدعاة كما لو أنه لم يكن مُهيَّأً عند الدخول. ويمكن اكتساب فهمٍ لسلوك وقواعد معدِّلات المعاملات على نحو أسهل من خلال الأمثلة (انظر أدناه) ورسائل المترجم.
void Foo(out int val)
{
val = 42;
}
void Bar(int val)
{
val = 42;
}
int importantValue = 1729;
Foo(out importantValue);
var result = importantValue == 42;
// => true
importantValue = 1729;
Bar(importantValue);
result = importantValue == 1729;
// => true
يجب إسناد قيم إلى معاملات out داخل الطريقة المستدعاة.
يمرِّر المعامل المزوَّد بالمعدِّل ref قيمةً إلى الطريقة المستدعاة. وعندما تُرجع الطريقة، سيعثر المستدعي على أي تحديثات أُجريت بواسطة الطريقة المستدعاة في ذلك المعامل.
void Foo(ref int val)
{
val *= 7;
}
int importantValue = 6;
Foo(ref importantValue);
return importantValue;
// => 42
يجب أن تكون معاملات ref متغيرات، لأن الطريقة المستدعاة ستعمل مباشرةً على المعامل كما يراه المستدعي.
المعدِّلان out و ref مطلوبان في توقيع الطريقة المستدعاة وفي موقع الاستدعاء.
بدأ مشروع سيارة التحكم عن بُعد الذي أطلقته في تمرين classes يسير على ما يرام (تهانينا!)، وبفضل عدد من صفقات الرعاية الأخيرة أصبح هناك مال في الميزانية مخصّص للتحسينات.
ويُستخدم جزء من الميزانية لتوفير بعض بيانات القياس عن بُعد.
ولإبقاء الرعاة راضين، ثُبِّتت لوحة على السيارة لعرض أسماء الرعاة أثناء سيرها على المضمار.
وستلاحظ أن إدخال هذه التقنيات الجديدة البرّاقة قلّل بشكل كبير من عمر بطارية السيارة.
نفّذ SetSponsors() لتأخذ اسم راعٍ واحدًا أو أكثر وتخزّنه في السيارة.
لاحظ أن وسيط الطريقة SetSponsors() مضمون ألّا يكون null.
نفّذ DisplaySponsor() لعرض الراعي المحدَّد. أول راعٍ يُمرَّر له sponsorNum يساوي 0، والثاني 1، وهكذا.
var car = RemoteControlCar.Buy();
car.SetSponsors("Exercism", "Walker Industries", "Acme Co.");
var sp2 = car.DisplaySponsor(sponsorNum: 1);
// => "Walker Industries"
نفّذ الطريقة RemoteControlCar.GetTelemetryData().
ينبغي أن تجعل GetTelemetryData() نسبة البطارية والمسافة المقطوعة بالأمتار متاحتين عبر معاملات out.
ينبغي أن تُرجع GetTelemetryData() القيمة false إذا كان وسيط serialNum أقل من القيمة المستلمة سابقًا. (ثمّة مشكلة ما تتعلق بتورّط عدة عُقد للقياس عن بُعد). في هذه الحالة سيُضبط serialNum على أعلى قيمة سابقة له، وستُضبط نسبة البطارية والأمتار المقطوعة كلتاهما على -1. أما إذا نجح الاستدعاء فيبقى serialNum دون تغيير.
var car = RemoteControlCar.Buy();
car.Drive();
car.Drive();
int serialNum = 4;
car.GetTelemetryData(ref serialNum, out int batteryPercentage, out int distanceDrivenInMeters);
// => true, 4L, 80, 4
serialNum = 1;
car.GetTelemetryData(ref serialNum, out batteryPercentage, out distanceDrivenInMeters);
// => false, 4L, -1, -1
نفّذ الطريقة TelemetryClient.GetBatteryUsagePerMeter().
ستستدعي هذه الطريقة RemoteControlCar.GetTelemetryData(). وإذا أرجعت GetTelemetryData() القيمة false أو لم تكن السيارة قد قِيقت بعد، فينبغي أن يُرجع هذا الإجراء "no data". وإذا أرجعت GetTelemetryData() القيمة true فينبغي أن تُرجع رسالة بالصيغة التالية "usage-per-meter=BATTERY-USAGE-PER-METER"، حيث الحساب هو (100 - نسبة البطارية الحالية) مقسومًا على المسافة المقطوعة بالأمتار حتى الآن.
var car = RemoteControlCar.Buy();
car.Drive();
car.Drive();
var tc = new TelemetryClient(car);
int serialNum = 4;
tc.GetBatteryUsagePerMeter(serialNum);
// => "usage-per-meter=5"
serialNum = 1;
tc.GetBatteryUsagePerMeter(serialNum);
// => "no data"
سجّل في Exercism لتتعلّم وتتقن C# عبر 62 مفهومًا178 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.