تعلم كيفية البرمجة ب #C


الدرس: التحويلات بين الأنواع


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

بين أنواع متوافقة: casting


لقد حان الوقت لاختيار أفضل أنواع الأداء ، وإفساح المجال أمام الـ casting
Casting هي ببساطة عملية تحويل قيمة نوع إلى آخر.
وبشكل أكثر تحديدًا ، يعمل مع الأنواع المتوافقة مع بعضها البعض ، وذلك يعني " التي تبدو متشابهة " .
على سبيل المثال ، الكل والكل الصغير متشابهان. للتذكير ، لدينا:
وصفنوع
shortعدد صحيح من -32،768 إلى 32،767
intعدد صحيح من -2147483648 إلى 2147483647
أنها تختلف فقط في قدرتها . و   short قد لا تحتوي على رقم 100000، على سبيل المثال، في حين أن int يمكنها ذلك.
لم نقم بذلك بعد ، لكن C# يتيح لنا القيام بما يلي:

short s = 200;
int i = s; 
لأنه من الممكن دائمًا تخزين عدد صحيح صغير في واحد كبير. بغض النظر عن قيمة s ،  i سوف تكون دائما قادرة على احتواء قيمتها. يبدو الأمر كما لو كان في سيارة ، إذا أمكننا استيعاب 5 في حافلة صغيرة ، فيمكننا بسهولة استيعاب 5 في حافلة.
العكس ليس صحيحًا بالطبع ، إذا حملنا 100 في حافلة ، فليس من المؤكد أننا سنكون قادرين على وضعهم في سيارة .
مما يعني أنه إذا فعلنا:

int i = 100000;
short s = i; 
سيكون لدينا خطأ التحويل البرمجي التالي:

    غير قادر على تحويل ضمنيًا النوع "int" إلى "short" . يوجد تحويل صريح (هل هناك cast مفقود؟)
ونعم ، كيف يمكننا الحصول على 100000 في نوع يمكن فقط أن يصل إلى 32767؟ المترجم يعرف هذا.
ستلاحظ أنه سيكون لدينا نفس الخطأ إذا حاولنا القيام بذلك:

int i = 200;
short s = i; 
و لكن لماذا ؟ و short غير قادرة على تخزين قيمة 200؟
نعم بالتأكيد ، ولكن المترجم يحذرنا على أي حال. يخبرنا:
"كن حذرًا ، فأنت تحاول نقل الأشخاص على متن الحافلة إلى حافلة صغيرة ، هل أنت متأكد؟" "
نريد أن نجيب عليه:
"نعم نعم ، أنا أعلم أن هناك عددًا قليلًا جدًا من الأشخاص على متن الحافلة وسيتمكنون من دخول حافلة صغيرة دون أي مشكلة. ثق بي ! "
( نتحدث في كثير من الأحيان مع المترجم! )
حسنا ، هذا مكتوب في C# على النحو التالي:

int i = 200;
short s = (short)i; 
نحن نستخدم ما يسمى cast صريح (explicit cast).
للقيام بمثل هذا ، قم فقط قبل المتغير الذي سيتم تحويله بوضع اسم النوع المطلوب بين قوسين. هذا يجعل من الممكن الإشارة إلى المترجم الخاص بنا بأننا نعرف ما نقوم به ، وأن الكل سيصلح بشكل صحيح في العدد الصحيح الصغير.
ولكن حذار ، المترجم يثق بنا. نحن رب العمل! هذا ينطوي على مسؤولية معينة ، فإنه ليس من الضروري أن تفعل أي شيء.
إذا فعلنا:

int i = 40000;
short s = (short)i;
Console.WriteLine(s);
Console.WriteLine(i); 
نحن نحاول احتواء عدد صحيح أكبر من اللازم في ما يمكن تخزين عدد صحيح صغير.
إذا قمنا بتشغيل طلبنا ، فسنحصل على:
c sharp .net framework
النتيجة ليست على الإطلاق واحدة المتوقعة. فعلنا أي شيء ، يعاقبنا C# .
في الواقع ، وبشكل أكثر دقة ، حدث ما يسمى الفائض. لقد رأينا هذا بالفعل في الفصل الخاص بالحلقات. حدث الشيء نفسه هنا. ذهب عدد صحيح صغير إلى الحد الأقصى لقيمة ومن ثم يحلق مرة أخرى من الحد الأدنى لقيمة.
باختصار ، كل هذا يعني أننا نحصل على نتيجة غير متوقعة. لذلك يجب علينا الانتباه إلى ما نقوم به وتكريم الثقة التي يتمتع بها المترجم. كن حذرا .
بطريقة مشابهة للعدد الصحيح و العدد الصحيح الصغير ، العدد الصحيح و double متشابهان بعض الشيء. كلاهما أنواع لاحتواء الأرقام. يمكن أن يحتوي الأول على أرقام كاملة ، والثاني يمكن أن يحتوي على أرقام فاصلة.
حتى نتمكن من القيام بكود C# التالي:

int i = 20;
double d = i; 
في الواقع ، الـ double أكثر دقة من الأعداد الصحيحة. إنه قادر على الحصول على أرقام بعد العلامة العشرية عندما لا يمكن للكل. هذا يجعل الـ double قادرا تمامًا على تخزين القيمة الكاملة لعدد صحيح دون فقد المعلومات.
ومع ذلك ، كما هو متوقع ، فإن العكس ليس ممكنًا. الكود التالي:

double prix = 125.55;
int valeur = prix; 
سينتج خطأ التحويل البرمجي التالي:

لا يمكن ضمنيًا تحويل النوع "double" إلى "int" . يوجد تحويل صريح (هل هناك cast   مفقودة؟)
في الواقع ، كون double أكثر دقة من عدد صحيح ، إذا وضعنا هذا double في عدد صحيح ، فسنخسر بشكل خاص الأرقام بعد العلامة العشرية.
مرة أخرى ، سيتعين علينا أن نطلب من المترجم أن يثق بنا!
"حسنًا ، هذا double ، لكن لا يهم ، أريد استخدامه كعدد صحيح!" نعم نعم ، حتى لو كنت أعلم أنني سأخسر الأرقام بعد العلامة العشرية ".
ما هو مكتوب في C# بهذه الوظيفة ، كما رأينا:

double prix = 125.55;
int valeur = (int)prix; // valeur تساوي 125
نسبق متغير prix حسب النوع الذي نريد تحويله إليه باستخدام الأقواس.
في هذه الحالة ، يمكننا استخدام هذا المدلى بها لاسترداد الجزء بأكمله من رقم الفاصلة العائمة.
انها رائعة جدا كتعليمات. لكن لا تنس أن هذه العملية ممكنة فقط مع الأنواع المتشابهة مع بعضها البعض.
على سبيل المثال ، الكود التالي مستحيل:

string nombre = "123";
int valeur = (int)nombre; 
لأن النوعين مختلفان للغاية ويتعارضان مع بعضهما البعض. حتى لو كانت سلسلة الحروف تمثل رقمًا.
سنرى لاحقًا كيفية تحويل سلسلة إلى عدد صحيح. في الوقت الحالي ، ينشئ Visual Studio Express خطأ في التحويل البرمجي:

غير قادر على تحويل النوع 'string' إلى 'int'
رسالة الخطأ واضحة الى حد ما. إنها لا تشير لنا حتى باستخدام cast ، فهو يرى أن الأنواع مختلفة حقًا!
لقد رأينا سابقًا أن التعدادات تمثل قيمًا كاملة. لذلك من الممكن استرداد عدد صحيح يتوافق مع قيمة التعداد بفضل cast .
على سبيل المثال ، مع مراعاة القائمة التالية:

enum Jours
{
    Lundi = 5, // lundi تساوي 5
    Mardi, // mardi تساوي 6
    Mercredi = 9, // mercredi تساوي 9
    Jeudi = 10, // jeudi تساوي 10
    Vendredi, // vendredi تساوي 11
    Samedi, // samedi تساوي 12
    Dimanche = 20 // dimanche تساوي 20
}
الكود التالي:

int valeur = (int)Jours.Lundi; // valeur تساوي 5
يحول التعداد إلى عدد صحيح.
سنرى في الدرس التالي أن cast أقوى بكثير من ذلك ، ولكن في الوقت الحالي ، ليس لدينا معرفة كافية لدراسة كل شيء.

بين أنواع غير متوافقة


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

string chaineAge = "20";
int age = Convert.ToInt32(chaineAge); // age تساوي 20
رغم أن هذه الوظيفة سهلة الاستخدام ، إلا أنها تشكل عيبًا في الحالة التي لا تمثل فيها السلسلة عددًا صحيحًا. في هذه المرحلة ، ستفشل عملية التحويل وسوف يرسل C# خطأ في وقت التشغيل.
مثلا :

string chaineAge = "vingt ans";
int age = Convert.ToInt32(chaineAge); 
إذا قمت بتشغيل هذا الكود، فسترى:
c sharp .net framework
وحدة التحكم تبين لنا ما يسمى استثناء ( exception). إنه ببساطة خطأ. سيكون لدينا الفرصة لدراسة الاستثناءات بمزيد من التفصيل في الدورة القادمة.
في الوقت الحالي ، نحتاج فقط أن نرى أن هذا لا يناسبنا. الخطأ واضح " تنسيق سلسلة الإدخال غير صحيح " ، لكن هذا يحدث في وقت التشغيل و "يعطل" برنامجنا بشكل تعسفي.
سنرى في الفصل الخاص بالاستثناءات كيفية التعامل مع الأخطاء.
داخليًا ، Convert.ToInt32() تستخدم الوظيفة وظيفة أخرى لإجراء التحويل ، وهذه هي الوظيفة int.Parse() . لذا بدلاً من استخدام وظيفة تستدعي وظيفة أخرى ، يمكننا استخدامها مباشرة ، على سبيل المثال:

string chaineAge = "20";
int age = int.Parse(chaineAge); // age يساوي 20
بالطبع ، سيحدث نفس الشيء تمامًا كما كان من قبل عندما لا تمثل السلسلة عددًا صحيحًا.
هناك، طريقة أخرى لتحويل السلسلة بأكملها و التي لا تسبب خطأ عندما يكون حجم غير صحيح وأن يخبرنا إذا كان تحويل ناجح أم لا، وهذا هو الأسلوب int.TryParse() التي تُستخدم على النحو التالي:

string chaineAge = "ab20cd";
int age;
if (int.TryParse(chaineAge, out age))
{
    Console.WriteLine("La conversion est possible, age vaut " + age);
}
else
{
    Console.WriteLine("Conversion impossible");
}
وسيكون لدينا:
c sharp .net framework
الوظيفة int.TryParse تعيدنا إلى حقيقة إذا كان التحويل جيدًا ، أو غير صحيح. يمكننا بالتالي القيام بأي إجراء وفقًا للنتيجة وذلك بفضل if/else . نقوم بتمرير مُدخلات السلسلة المراد تحويلها والمتغير حيث نريد تخزين نتيجة التحويل. الكلمة الرئيسية " out" تعني فقط أن المتغير قد تغير بالوظيفة ، وسوف نرى بالضبط ما هو عليه في الدورة المقبلة.
الأساليب التي رأيناها للتو Convert.ToString() أو int.TryParse() تم رفضها عمومًا لجميع أنواع القواعد ، على سبيل المثال double.TryParse() أو Convert.ToDecimal() ، إلخ.

في الخلاصة


  • من الممكن ، من خلال عملية cast ، تحويل قيمة نوع ما إلى نوع آخر عندما تكون متوافقة مع بعضها البعض.
  • يتم استخدام cast الصريح عن طريق بادئة متغير بنوع محدد بين قوسين.
  • يحتوي .NET Framework على وظائف لتحويل الأنواع غير المتوافقة مع بعضها البعض إذا كانت قريبة من الدلالة.