نحوه راه اندازی گوشی های هوشمند و رایانه های شخصی پرتال اطلاعاتی

ریخته گری به شناور c#. تبدیل نوع

بیایید به سراغ مثال ها برویم. کلاس آزمایش کردن, حاوی مثال‌ها، مجموعه‌ای از داده‌ها از انواع مختلف است که عملیاتی را انجام می‌دهند که تبدیل نوع را نشان می‌دهد. اینم توضیحات کلاس

تست: با استفاده از سیستم.
فضای نام TypesProject
{
تست کلاس عمومی{
/// < خلاصه>
/// مجموعه ای از فیلدهای اسکالر از انواع مختلف.
///
بایت خصوصی ب= 255;
خصوصی int x= 11 ;
واحد خصوصی ux= 1111 ;
شناور خصوصی y= 5.5f;
دوگانه خصوصی= 5.55;
رشته خصوصی s= "سلام!"؛
رشته خصوصی si= "25";
شی خصوصی obj= شیء جدید ();
// بعدی متدهای کلاس هستند که در طول مسیر ارائه می شوند
// توضیحات نمونه
}
}

مجموعه داده یک کلاس شامل داده های اسکالر از نوع حسابی مربوط به انواع مقادیر، متغیرهای نوع رشته و نوع است. هدف - شی, متعلق به انواع مرجع بسته را در نظر بگیرید (خصوصی) متد این کلاس یک رویه است WhosWhoبا استدلال کلاسی رسمی هدف - شی. رویه نام آرگومان ارسال شده به آن، نوع و مقدار آن را در کنسول چاپ می کند.

اینم متنش:

/// < خلاصه>
/// این روش اطلاعات مربوط به نوع را در کنسول چاپ می کند و
/// مقدار آرگومان واقعی. رسمی
/// آرگومان از نوع استهدف - شی. استدلال واقعی
/// می تواند از هر نوع باشد، از همیشه
/// تبدیل ضمنی به نوع مجاز استهدف - شی.
///
/// نامدومینبحث و جدل
/// اعتراف کنیمبحث و جدلهرنوع
خلأ خصوصی WhoIsWho (نام رشته، شیء هر){
Console.WriteLine ("نوع{0} است (1), ارزش است{2}",
نام، any.GetType ()، any.ToString ());
}

اینجا باز است (عمومی) روش کلاس آزمایش کردن, که در آن متد به طور مکرر فراخوانی می شود WhosWhoبا آرگومان های مختلف:

/// < خلاصه>
/// اطلاعاتی در مورد نوع و مقدار دریافت کنید
/// از آرگومان تصویب شده - متغیر یا عبارت
/// خلاصه>
عمومی void WhoTest (){
WholsWho ("x"، x);
WholsWho ("ux"، ux)؛
WhoIsWho ("y"، y);
WhoIsWho ("dy"، dy);
WhoIsWho ("s"، s);
WhoIsWho ("11+ 5.55 + 5.5f "، 11+ 5.55 + 5.5f)؛
obj= 11 + 5.55 + 5.5f;
WhoIsWho(" obj", obj);
}

توجه داشته باشید که نهاد هر- استدلال کلاس رسمی هدف - شی, که در هر فراخوانی به صورت پویا نوع را با ارتباط با شی داده شده توسط آرگومان واقعی تغییر می دهد. بنابراین، نوع آرگومان گزارش شده به کنسول، نوع آرگومان واقعی است. همچنین توجه داشته باشید که کلاسی که از کلاس به ارث برده شده است هدف - شیروش Gettypeنوع FCL را برمی گرداند، یعنی نوعی که نوع زبان را نشان می دهد و کار با آن در هنگام اجرای ماژول واقعاً انجام می شود. در اکثر فراخوانی ها، آرگومان واقعی یک متغیر است - ویژگی مربوط به کلاس آزمایش کردن, اما در یک مورد، یک عبارت حسابی معمولی ارسال می شود که به طور خودکار به یک شی تبدیل می شود. وضعیت مشابهی هنگام انجام یک تکلیف در رویه مورد بررسی اتفاق می افتد.

در شکل 11 خروجی کنسول را هنگام فراخوانی متد نشان می دهد WhoTestدر روش فوق اصلیکلاس کلاسی.

شکل 11. چاپ نتایج آزمون WhoTest

تبدیل نوع کجا، چگونه و چه زمانی انجام می شود؟

نیاز به تبدیل نوع در عبارات، تخصیص ها، جایگزینی آرگومان های روش رسمی با آرگومان های واقعی ایجاد می شود.

اگر هنگام ارزیابی یک عبارت، عملوندهای یک عملیات دارای انواع مختلفی باشند، لازم است آنها را به یک نوع ریخته کنیم. چنین نیازی نیز زمانی به وجود می آید که عملوندها از یک نوع باشند، اما با نوع عملیات ناسازگار باشد. به عنوان مثال، هنگام اجرای جمع، عملوندهای نوع بایتباید برای تایپ ریخته گری شود بین المللی, از آنجایی که اضافه بر روی بایت تعریف نشده است. هنگام انجام یک تکلیف ایکس= هنوع منبع هو نوع هدف ایکسباید سازگار باشد به همین ترتیب، هنگام فراخوانی یک متد، نوع منبع و هدف آرگومان های واقعی و رسمی نیز باید سازگار باشند.

تبدیل نوع مرجع

از آنجایی که عملیات روی انواع مرجع تعریف نشده است (استثنا رشته ها هستند، اما عملیات روی آنها، از جمله تخصیص، مانند انواع مقادیر انجام می شود)، نیاز به آنها فقط در هنگام تخصیص و فراخوانی متدها ایجاد می شود.

تبدیل ها را در عبارات تایپ کنید

در سی شارپ، این گونه تبدیل ها به صریح و ضمنی تقسیم می شوند. تبدیل های ضمنی آن دسته از تبدیل هایی هستند که نتیجه آنها همیشه موفقیت آمیز بوده و منجر به از بین رفتن دقت داده ها نمی شود. تبدیل ضمنی به صورت خودکار انجام می شود. برای داده های حسابی، این بدان معنی است که در تبدیل های ضمنی، محدوده نوع هدف شامل محدوده نوع اصلی است. به عنوان مثال، تبدیل از نوع بایتدر نوع بین المللیبه ضمنی اشاره دارد زیرا محدوده مانند است بایتزیر مجموعه ای از محدوده است بین المللی. این تبدیل همیشه موفقیت آمیز است و نمی تواند منجر به از دست دادن دقت شود.

تبدیل‌های صریح تبدیل‌های قانونی هستند که تضمینی برای موفقیت ندارند یا ممکن است منجر به از دست دادن دقت شوند. چنین تبدیل های بالقوه خطرناکی باید به صراحت توسط برنامه نویس مشخص شود. تبدیل از نوع بین المللیدر نوع بایتبه صریح اشاره دارد زیرا ناامن است و می تواند منجر به از دست دادن ارقام قابل توجه شود. توجه داشته باشید که همه انواع دارای تبدیل صریح نیستند. در این مورد، مکانیسم های تبدیل نوع دیگری مورد نیاز است که بعداً مورد بحث قرار خواهد گرفت.

تبدیل در یک نوع حسابی

نوع حسابی، همانطور که در جدول نوع داده نشان داده شده است، به 11 زیرگروه تقسیم می شود. در شکل شکل 12 نموداری از تبدیل ها را در یک نوع حسابی نشان می دهد.

شکل 12. سلسله مراتب تبدیل ها در یک نوع حسابی

نمودار نشان داده شده در شکل به شما امکان می دهد به تعدادی از سوالات مهم مربوط به وجود تبدیل بین انواع پاسخ دهید. اگر نمودار یک مسیر (فلش) را از نوع A به نوع B نشان دهد، این به معنای وجود یک تبدیل ضمنی از نوع A به نوع B است. همه تبدیل‌های دیگر بین انواع فرعی از نوع حسابی وجود دارند، اما صریح هستند. توجه داشته باشید که هیچ چرخه ای در نمودار وجود ندارد، همه فلش ها یک طرفه هستند، بنابراین تبدیل معکوس به ضمنی همیشه باید به طور صریح مشخص شود.

مسیر نشان داده شده در نمودار می تواند بسیار طولانی باشد، اما این بدان معنا نیست که کل دنباله تبدیل ها در این مسیر در حال انجام است. وجود یک مسیر فقط نشان دهنده وجود یک تبدیل ضمنی است و خود تبدیل تنها یک بار از مبدا نوع A به مقصد نوع B انجام می شود.

گاهی اوقات وضعیتی پیش می آید که در آن برای یک نوع منبع چندین نوع مقصد می تواند به طور همزمان وجود داشته باشد و لازم است یک هدف - نوع مقصد انتخاب شود. چنین مشکلات انتخابی برای مثال هنگام کار با متدهای بارگذاری شده در کلاس ها به وجود می آیند.

قانون انتخاب یک پیاده سازی هنگام فراخوانی یک متد به شرح زیر است: پیاده سازی انتخاب می شود که مسیر تبدیل مشخص شده در نمودار برای آن کوتاه تر باشد. اگر تطابق دقیق پارامترها بر اساس نوع (مسیر طول 0) وجود داشته باشد، البته این پیاده سازی انتخاب خواهد شد.

بیایید یک مورد آزمایشی دیگر را بررسی کنیم. به کلاس آزمایش کردنیک گروه از روش های اضافه بار گنجانده شده است بارگیریبا یک و دو استدلال این روش ها عبارتند از:

/// < خلاصه>
/// گروهی از متدهای بارگذاری شدهبارگیری
/// با یک یا دو آرگومان نوع حسابی.
/// اگر آرگومان واقعی یکی باشد، یکی از
/// متدهایی که بیشترین تطابق را با نوع آرگومان دارند.
/// هنگام فراخوانی متدی با دو آرگومان، این امکان وجود دارد
/// تعارض در انتخاب روش مناسب، در نتیجه
/// به یک خطای زمان کامپایل.
///
Private void OLoad (float par){
Console.WriteLine ("مقدار شناور{0}", همتراز)؛
}
/// < خلاصه>
/// روش اضافه باربارگیریبا یک پارامتر نوعطولانی
///
///
خلا خصوصی OLAd (طولان برابر){
Console.WriteLine ("مقدار طولانی (0)"، par);
}
/// < خلاصه>
/// روش اضافه بارOnLoadبا یک پارامتر نوعطولانی
///
///
Private void OLAd (طول همتراز){
Console.WriteLine ("مقدار طولانی (0)"، par);
}
/// < خلاصه>
/// روش اضافه باربارگیریبا یک پارامتر نوعدو برابر
///
///
Private void OnLoad (دو برابر){
Console.WriteLine ("مقدار دوگانه (0)"، par);
}
/// < خلاصه>
/// روش اضافه باربارگیریبا دو پارامتر مانندطولانیوطولانی
///
///
///
Private void OLoad (long par1، long par2){
Console.WriteLine ("long par1{0}, طولانی par2{1}", par1، par2)؛
}
/// < خلاصه>
/// روش اضافه باربارگیریبا دو پارامتر مانند
/// دو برابرودو برابر
///
///
///
Private void OLAd (دو برابر 1، دو برابر 2){
Console.WriteLine ("double par1{0}, دو برابر 2{1}", par1، par2)؛
}
/// < خلاصه>
/// روش اضافه باربارگیریبا دو پارامتر مانند
/// بین المللیوشناور
///
///
///
Private void OLoad (int par1، float par2){
Console.WriteLine ("int par1{0}, float par2{1}", par1، par2)؛
}

همه این روش ها به اندازه کافی ساده هستند. آنها اطلاعاتی در مورد نوع و ارزش آرگومان های ارسال شده ارائه می دهند.

در اینجا یک روش تست است که متد را فراخوانی می کند بارگیریبا تعداد و انواع مختلف آرگومان ها:

/// < خلاصه>
/// فراخوانی یک متد اضافه باربارگیری. بسته به
/// نوع و تعداد آرگومان ها یکی از متدهای گروه فراخوانی می شود.
///
عمومی void OLoadTest (){
OLload (x)؛
OLoad (ux)؛
OLoad (y)؛
OLoad (dy)؛
// OLoad (x، ux)؛
// درگیری: (int، شناور)و(طولانی، طولانی)
OLoad (x, (شناور) ux)؛
OLoad (y، dy)؛
بارگیری(ایکس, دو);
}

توجه داشته باشید که یکی از تماس ها نظر داده می شود زیرا منجر به درگیری در مرحله ترجمه می شود. برای حذف تضاد هنگام فراخوانی متد، باید تبدیل صریح آرگومان را مشخص می‌کردیم که در خط بعد از خط نظر نشان داده می‌شود. نتیجه آزمایش OLoadTestدر شکل نشان داده شده است. سیزده.

شکل 13. چاپ نتایج OLoadTest

تبدیل های صریح

همانطور که قبلا ذکر شد، تبدیل های صریح می توانند به دلیل از دست دادن دقت خطرناک باشند. بنابراین، آنها به دستور برنامه نویس اجرا می شوند - او تمام مسئولیت نتایج را بر عهده دارد.

تبدیل رشته ها

یک کلاس مهم از تبدیل ها تبدیل به رشته و بالعکس است. تبدیل به یک نوع رشته همیشه تعریف می شود، زیرا همه انواع از نوادگان کلاس پایه هستند هدف - شی, و بنابراین، روش را داشته باشید ToString(). اجرای مناسب این روش برای انواع توکار تعریف شده است. به طور خاص، برای تمام زیرگروه های نوع حسابی، روش ToString() رشته ای را که مقدار حسابی مربوطه را مشخص می کند به شکل مناسب برمی گرداند. توجه داشته باشید، روش ToStringرا می توان به طور صریح فراخوانی کرد، اما اگر یک فراخوانی صریح مشخص نشده باشد، هر زمان که زمینه نیاز به تبدیل به یک نوع رشته داشته باشد، به طور ضمنی فراخوانی می شود. در اینجا یک مثال مرتبط آورده شده است:

/// < خلاصه>
/// نمایش تبدیل داده ها از انواع مختلف به رشته.
///
عمومی void ToStringTest ()
{
س= " ولادیمیرپتروف ";
s1= " سن: ";
ux= 27;
س= س+ s1+ ux.ToString ();
s1= " حقوق: ";
دو= 2700.50;
س= س+ s1+ dy;
WhoIsWho(" س", س);
}

نتیجه این روش در شکل نشان داده شده است. 14.

شکل 14. چاپ نتایج ToStringTest

تبدیل از نوع رشته به انواع دیگر، مانند حساب، باید به صراحت انجام شود. اما هیچ تبدیل صریحی بین حساب و رشته وجود ندارد. مکانیسم های دیگری مورد نیاز است، و آنها در C# موجود هستند. برای این منظور می توانید از متدهای کلاس مربوطه استفاده کنید تبدیلکتابخانه FCL در فضای نام تعبیه شده است سیستم. بیایید مثالی بزنیم:

/// < خلاصه>
/// نمایش تبدیل یک رشته به داده از انواع مختلف.
///
خالی عمومی FromStringTest (){
س= " واردسن ";
Console.WriteLine (های)؛
s1= Console.ReadLine ();
ux= Convert.ToUInt32 (s1);
WhoIsWho("سن: "،ux);
س= "حقوق را وارد کنید";
Console.WriteLine (های)؛
s1= Console.ReadLine ();
دو= Convert.ToDouble (s1);
کیست کی ("حقوق: ", dy)؛
}

این مثال ورودی از کنسول انواع مختلف داده را نشان می دهد. داده ها از کنسول با روش خوانده می شوند ReadLineیا خواندن, همیشه یک رشته را نشان می دهد که سپس باید به نوع مورد نظر تبدیل شود. برای این کار، متدهای کلاس مربوطه فراخوانی می شوند. تبدیل. طبیعتاً، برای موفقیت در تبدیل، رشته باید دارای مقداری در قالبی باشد که امکان چنین تبدیلی را فراهم کند. به عنوان مثال توجه داشته باشید که هنگام نوشتن مقدار یک عدد، برای برجسته کردن قسمت کسری باید از کاما استفاده شود، نه نقطه. در غیر این صورت یک خطای زمان اجرا رخ خواهد داد.

در شکل 15 نتایج خروجی و ورودی از کنسول را هنگام اجرای این رویه نشان می دهد.

شکل 15. چاپ نتایج FromStringTest

تبدیل نوع داده ضمنی توسط کامپایلر C ++ انجام می شود، در حالی که تبدیل نوع داده صریح توسط خود برنامه نویس انجام می شود. در مورد تبدیل نوع داده، من موارد زیر را خواهم گفت: "نتیجه هر محاسبه به دقیق ترین نوع داده از آن دسته از انواع داده هایی که در محاسبه دخیل هستند، تبدیل می شود." برای مثالی گویا، جدولی را با تبدیل نوع داده ارائه خواهم کرد. بیایید به عملیات تقسیم در جدول نگاه کنیم. ما به عنوان یک نوع داده عدد صحیح می گیریم بین المللیخوب، ما یک نوع داده واقعی خواهیم داشت شناور.

جدول 1 - تبدیل نوع داده صریح و ضمنی در C ++
ایکس y نتیجه تقسیم مثال
سود سهام تقسیم کننده خصوصی x = 15 y = 2
بین المللی بین المللی بین المللی 15/2=7
بین المللی شناور شناور 15/2=7.5
شناور بین المللی شناور 15/2=7.5

جدول نشان می دهد که با تغییر متغیرها در مکان های مختلف، نتیجه یکسان می ماند (در مورد ما، این تقسیم کننده و تقسیم کننده است). همه چیز در مورد تبدیل نوع داده ضمنی است. در مورد تبدیل صریح، برای انجام برخی دستکاری ها، در نتیجه تغییر نتیجه محاسبه ضروری است. ساده ترین راه برای تبدیل صریح انواع داده ها، به عنوان مثال: فرض کنید باید چنین اعدادی را به 15 و 2 تقسیم کنیم، تقسیم می کنیم! 15/2 = 7. نتیجه مانند جدول است. اما اگر با این تقسیم تبدیلات جزئی انجام دهید، به عنوان مثال: 15.0 / 2 = 7.5، عدد 15 واقعی است، نتیجه واقعی خواهد بود. خود عدد 15 از نظر ریاضیات تغییر نکرده است، زیرا 15 = 15.0 است. همین تکنیک را می‌توان برای دو به کار برد، نتیجه یکسان خواهد بود، اما می‌توان آن را همزمان روی دو عدد اعمال کرد، اما چرا، اگر یکی از این دو کافی است.

روش دیگری برای تبدیل صریح انواع داده ها:

Float (15) / 2 // نتیجه 7.5 است، عدد 15 به نوع داده واقعی float تبدیل می شود. دو برابر (15) / 2 // نتیجه 7.5 است - یکسان !!!

C ++ همچنین یک عملیات ریخته گری یکنواخت را ارائه می دهد:

Static_cast(/ * متغیر یا عدد * /)

مثال: static_cast (15) / 2 نتیجه 7.5 است
مثال با یک متغیر:

Int ret = 15; static_cast (ret) / 2 // نتیجه 7.5 است

در مورد یک متغیر، باید بدانید که در خط 2، متغیر ret به نوع داده float تبدیل نمی شود، بلکه فقط یک کپی موقت از متغیر ret با نوع داده float ایجاد می شود. بیایید در عمل تمام روش های تبدیل صریح و ضمنی انواع داده ها را در نظر بگیریم.

// pryeobrazovanie.cpp: نقطه ورودی برنامه کنسول را تعریف می کند. #include "stdafx.h" #include #عبارتند از با استفاده از namespace std. int _tmain (int argc, _TCHAR * argv) (int int_value15 = 15, int_value2 = 2; // دو متغیر از نوع int float float_value15 = 15, float_value2 = 2؛ // دو متغیر co floatut را اعلام کنید.<< fixed << setprecision(2) // определяем, при выводе чисел с плавающей точкой, два знака после запятой << "15 / 2 = " << int_value15 / int_value2 << endl //неявное преобразование типов данных << "15 / 2 = " << int_value15 / float_value2 << endl //неявное преобразование типов данных << "15 / 2 = " << float_value15 / int_value2 << endl //неявное преобразование типов данных << "15 / 2 = " << float_value15 / float_value2 << endl; //неявное преобразование типов данных cout << "15.0 / 2 = " << 15.0 / 2 << endl // явное преобразование типа данных, число 15.0 - число с плавающей точкой << "15 / 2.0 = " << 15 / 2.0 << endl; // явное преобразование типа данных, число 2.0 - число с плавающей точкой cout << "float(int_value15) / int_value2 = " << float(int_value15) / int_value2 << endl // явное преобразование типа данных << "15 / double(2) = " << 15 / double(2) << endl; // используя приводимый тип как функцию cout << "static_cast(15) / 2 = " << static_cast(15) / 2 << endl // унарная операция приведения типа << "static_cast(15) = " << static_cast(15) << endl // можно печатать различные символы из таблицы ASCII, << "static_cast(20) = " << static_cast(20) << endl; // в скобочках прописываем код символа, который находим в таблице ASCII system("pause"); return 0; }

V خط 5متصل ، این کتابخانه برای استفاده از دستکاری های مختلف مورد نیاز است، در مورد ما -دقت تنظیم ثابت (). V خط 10به طور خاص دو متغیر مانند ایجاد شده استبین المللی ، به طور مشابه دو متغیر از نوع ایجاد کردشناور در خط 11، این متغیرها برای تبدیل مقادیر آنها به انواع داده های دیگر مورد نیاز خواهند بود. Vخط 12بعد از اپراتورکوت و عملیات را به جریان خروجی تغییر دهید << دو دستکاری کننده وجود داردثابت و تنظیم دقیق (). دستکاری کننده ثابت - این یک دستکاری کننده پارامتری نیست، زیرا هیچ پارامتری را نمی پذیرد، بدون پرانتز نوشته می شود. این دستکاری همراه با یک دستکاری پارامتری استفاده می شوددقت تنظیم () و نمایش ثابت اعشار را انجام می دهد. یک دستکاری کنندهدقت تنظیم () تعداد ارقام اعشاری و آنچه در پرانتز نشان داده شده است را نشان می دهد. Vخطوط 13، 14، 15، 16نمونه هایی از تبدیل نوع داده ضمنی نشان داده شده است، این نمونه ها از آن گرفته شده اندمیز 1... V خطوط 17، 18یکی از راه های تبدیل صریح داده ها را نشان می دهد. ماهیت این روش این است که شما باید یک کاما و صفر را به یک عدد صحیح اضافه کنید. Vخطوط 19، 20تبدیل صریح با استفاده از انواع castable به عنوان توابع انجام می شود که در داخل پرانتز آنها باید مقدار یا متغیری را که باید تبدیل شود مشخص کنید. در خطوط 21، 22، 23، یک تبدیل نوع داده صریح با استفاده از یک عملیات تبدیل داده یکنواخت انجام می شود. پرانتز نشان دهنده متغیر یا مقداری است که باید تبدیل شود و کاراکترها قاب می شوند < > نوع داده ای که باید به آن تبدیل شود. نمونه ای از نحوه عملکرد برنامه در زیر نشان داده شده است (شکل 1 را ببینید).

شکل 1 - تبدیل صریح و ضمنی انواع داده های C ++

V خطوط 22، 23یک عملیات تبدیل داده یکنواخت انجام می شود و اعداد 15 و 20 به char تبدیل می شوند. این نوع داده هنوز برای شما شناخته شده نیست، اما به یاد داشته باشید که char نوع داده برای ذخیره سازی است. بنابراین، از شکل 1می توانید ببینید که نمادهایی در انتها وجود دارد. این کاراکترها با تبدیل اعداد به char به دست آمده اند. اعداد از کدهایی بودند. بنابراین، اگر شما نیاز به نمایش هر کاراکتری از جدول ASCII دارید، این کار را می توان همانطور که در نشان داده شده است انجام داد خطوط 22، 23، در حالی که فقط کد مورد نیاز را جایگزین می کند.

تبدیل ها را تایپ کنید

در برنامه نویسی غیر معمول نیست که مقادیر متغیرهای یک نوع به متغیرهای نوع دیگر اختصاص داده شود. به عنوان مثال، در قطعه کد زیر، یک int به یک float اختصاص داده شده است:

Int i; شناور f; i = 10; f = i; // یک مقدار صحیح به یک متغیر شناور اختصاص دهید

اگر انواع داده های سازگار در یک عملیات تخصیص مخلوط شوند، آنگاه مقدار سمت راست اپراتور تخصیص به طور خودکار به نوع نشان داده شده در سمت چپ آن تبدیل می شود. بنابراین در قطعه کد بالا مقدار i ابتدا به float تبدیل می شود و سپس به f اختصاص می یابد. با این حال، به دلیل کنترل دقیق نوع، همه انواع داده در C # کاملاً سازگار نیستند و بنابراین، همه تبدیل‌های نوع به طور ضمنی مجاز نیستند. به عنوان مثال، انواع bool و int ناسازگار هستند. درست است، تبدیل انواع ناسازگار هنوز می تواند توسط به ارمغان آوردن... Typecasting اساساً به معنای تبدیل آنها به صراحت است.

تبدیل خودکار نوع

هنگامی که داده های یک نوع به متغیری از نوع دیگر اختصاص داده می شود، تبدیل ضمنیانواع به طور خودکار تحت شرایط زیر رخ می دهد:

  • هر دو نوع سازگار هستند
  • دامنه نمایش اعداد نوع هدف گسترده تر از نوع اصلی است

اگر هر دوی این شرایط برآورده شود، پس تبدیل گسترده... به عنوان مثال، int به اندازه کافی بزرگ است که تمام مقادیر معتبر بایت را در خود جای دهد، و علاوه بر این، int و بایت هر دو نوع عدد صحیح سازگار هستند و بنابراین تبدیل ضمنی برای آنها کاملا امکان پذیر است.

انواع عددی، هر دو عدد صحیح و ممیز شناور، برای انجام تبدیل های گسترده با یکدیگر کاملاً سازگار هستند. بیایید یک مثال را در نظر بگیریم:

استفاده از سیستم؛ با استفاده از System.Collections.Generic. با استفاده از System.Linq؛ با استفاده از System.Text. فضای نام ConsoleApplication1 (برنامه کلاس (حذف استاتیک اصلی (رشته آرگ) (کوتاه num1, num2؛ num1 = 10؛ num2 = 15؛ Console.WriteLine ("(0) + (1) = (2)"، num1، num2، مجموع (num1، num2))؛ Console.ReadLine ();) int استاتیک مجموع (int x، int y) (بازگشت x + y؛)))

توجه داشته باشید که متد Sum () انتظار دارد دو پارامتر int وارد شود. اما در روش Main () در واقع از دو متغیر از نوع short عبور داده می شود. در حالی که ممکن است این یک عدم تطابق نوع به نظر برسد، برنامه بدون خطا کامپایل و اجرا می شود و همانطور که انتظار می رود عدد 25 را برمی گرداند.

دلیل اینکه کامپایلر این کد را از نظر نحوی صحیح می داند این است که از دست دادن داده در اینجا غیرممکن است. از آنجایی که حداکثر مقدار (32767) که یک short می تواند نگه دارد به خوبی در محدوده یک int است (که حداکثر مقدار آن 2147483647 است)، کامپایلر به طور ضمنی هر short را به یک int گسترش می دهد. به طور رسمی، اصطلاح "افزونه" برای نشان دادن یک ریخته گری ضمنی به سمت بالا استفاده می شود که منجر به از دست دادن داده نمی شود.

ریخته گری انواع ناسازگار

در حالی که تبدیل‌های ضمنی مفید هستند، اما نمی‌توانند تمام نیازهای برنامه‌نویسی را برآورده کنند، زیرا فقط به تبدیل‌های گسترده از انواع سازگار اجازه می‌دهند. و در تمام موارد دیگر، باید به تبدیل نوع متوسل شوید. به ارمغان آوردندستوری به کامپایلر برای تبدیل نتیجه ارزیابی یک عبارت به نوع مشخص شده است. این نیاز به یک تبدیل نوع صریح دارد. شکل کلی تایپ کست به صورت زیر است:

(نوع_هدف) عبارت

اینجا target_typeنشان دهنده نوعی است که می خواهید عبارت مشخص شده را به آن تبدیل کنید.

اگر ریخته گری منجر شود تغییر شکل باریک، ممکن است برخی از اطلاعات از بین برود. به عنوان مثال، در نتیجه ریخته‌گری از نوع long به نوع int، اگر مقدار نوع long بزرگتر از محدوده نمایش اعداد برای نوع int باشد، برخی از اطلاعات از بین می‌رود، زیرا مهم‌ترین بیت‌های این مقدار عددی کنار گذاشته می‌شوند. . وقتی یک مقدار ممیز شناور به یک مقدار صحیح ریخته می شود، بخش کسری این مقدار عددی در نتیجه برش از بین می رود. بنابراین، اگر مقدار 1.23 را به یک متغیر صحیح اختصاص دهید، در نتیجه تنها کل قسمت از عدد اصلی (1) در آن باقی می‌ماند و قسمت کسری آن (0.23) از بین می‌رود. بیایید مثالی بزنیم:

استفاده از سیستم؛ با استفاده از System.Collections.Generic. با استفاده از System.Linq؛ با استفاده از System.Text. namespace ConsoleApplication1 (کلاس برنامه (حذف استاتیک اصلی (رشته آرگ) (int i1 = 455، i2 = 84500؛ اعشاری dec = 7.98845m؛ // دو عدد از نوع int // برای تایپ کوتاه Console.WriteLine ((کوتاه) i1 ارسال کنید ) ؛ Console.WriteLine ((کوتاه) i2)؛ // ارسال اعشاری // به int Console.WriteLine ((int) dec)؛ Console.ReadLine ();)))

نتیجه این برنامه خواهد بود:

لطفاً توجه داشته باشید که متغیر i1 به درستی به نوع short تبدیل شده است مقدار آن در محدوده این نوع داده است. با تبدیل dec به int قسمت عدد صحیح آن عدد را برمی گرداند. تبدیل متغیر i2 برگردانده شد مقدار سرریز 18964 (یعنی 84500 - 2 * 32768).

رهگیری تغییر شکل داده های باریک

در مثال قبلی، ریختن متغیر i2 به short قابل قبول نیست، زیرا ناشی می شود از دست رفتن داده ها... C# کلمات کلیدی مانند بررسی شدو بدون علامتتا اطمینان حاصل شود که از دست دادن داده ها بی توجه نمی ماند.

به طور پیش فرض، زمانی که هیچ اقدام اصلاحی مناسبی انجام نمی شود، شرایط سرریز و زیر جریان بدون خطا رخ می دهد. دو راه برای رسیدگی به شرایط سرریز و زیر جریان در برنامه شما وجود دارد. این کار را می توان به صورت دستی و با تکیه بر دانش و مهارت های برنامه نویسی شما انجام داد.

عیب این روش این است که حتی در صورت به کارگیری حداکثر تلاش، انسان همچنان یک فرد باقی می ماند و برخی از اشتباهات ممکن است از چشمان او دور شود.

خوشبختانه C# کلمه کلیدی بررسی شده را ارائه می دهد. هنگامی که یک دستور (یا بلوک دستور) در یک زمینه بررسی شده محصور می شود، کامپایلر C# دستورات CIL اضافی را برای بررسی شرایط سرریز که می تواند از جمع، ضرب، تفریق یا تقسیم دو نوع داده عددی ناشی شود، تولید می کند.

اگر شرایط سرریز در زمان اجرا رخ دهد، یک استثنا ایجاد می شود System.OverflowException... بیایید به مثالی نگاه کنیم که در آن مقدار استثنا را به کنسول ارسال می کنیم:

استفاده از سیستم؛ با استفاده از System.Collections.Generic. با استفاده از System.Linq؛ با استفاده از System.Text. namespace ConsoleApplication1 (برنامه کلاس (حذف استاتیک اصلی (عرض رشته) (بایت var1 = 250؛ بایت var2 = 150؛ امتحان کنید (جمع بایت = بررسی شده ((بایت) (var1 + var2))؛ Console.WriteLine ("جمع: (0) ) "، sum);) catch (OverflowException ex) (Console.WriteLine (ex.Message); Console.ReadLine ();))))

نتیجه این برنامه:

یک بررسی در کل پروژه برای شرایط سرریز تنظیم کنید

اگر برنامه‌ای می‌سازید که در آن سرریز هرگز نادیده گرفته نمی‌شود، ممکن است متوجه شوید که با کلمه کلیدی علامت‌گذاری شده، تعداد زیادی از خطوط کد آزار دهنده است. در چنین حالتی، به عنوان یک جایگزین، کامپایلر C # پشتیبانی می کند پرچم / بررسی شد... هنگامی که این پرچم فعال می شود، تمام عملیات حسابی در کد به طور خودکار برای سرریزهای احتمالی بررسی می شود، بدون استفاده از کلمه کلیدی علامت زده شده برای هر یک از آنها. تشخیص سرریز نیز منجر به ایجاد استثنای مربوطه در زمان اجرا می شود.

برای فعال کردن این پرچم در ویژوال استودیو 2010، صفحه ویژگی های پروژه را باز کنید، به تب Build بروید، روی دکمه Advanced کلیک کنید و در کادر محاوره ای که باز می شود، کادر را علامت بزنید. سرریز/سرریز حسابی را بررسی کنید:

توجه به این نکته مهم است که C# کلمه کلیدی را ارائه می دهد بدون علامت، که به شما امکان می دهد در موارد فردی پرتاب یک استثناء سرریز را غیرفعال کنید.

بنابراین، برای خلاصه کردن استفاده از کلیدواژه‌های علامت‌دار و بدون علامت در سی #، توجه داشته باشید که به‌طور پیش‌فرض، سرریز حسابی در زمان اجرا دات‌نت نادیده گرفته می‌شود. اگر نیاز به پردازش اپراتورهای جداگانه دارید، باید از کلمه کلیدی علامت زده استفاده کنید، و اگر نیاز دارید همه خطاهای مربوط به سرریز را در برنامه ببینید، باید پرچم / علامت زده شده را فعال کنید. تا آنجا که به کلمه کلیدی علامت نخورده مربوط می شود، می توان از آن زمانی استفاده کرد که بلوکی از کد وجود داشته باشد که سرریز در آن قانونی است (و بنابراین نباید منجر به ایجاد استثنا در زمان اجرا شود).

آخرین به روز رسانی: 30.07.2018

در فصل قبل در مورد تبدیل اشیا از انواع ساده صحبت کردیم. حال به مبحث تبدیل اشیاء کلاس می پردازیم. فرض کنید سلسله مراتب کلاس زیر را داریم:

Class Person (نام رشته عمومی (get; set;) public Person (نام رشته) (Name = name;) public void Display () (Console.WriteLine ($ "Person (Name)");)) کلاس Employee: Person ( شرکت رشته عمومی (دریافت؛ مجموعه؛) کارمند عمومی (نام رشته، شرکت رشته): پایه (نام) (شرکت = شرکت؛)) کلاس مشتری: شخص (بانک رشته عمومی (دریافت؛ مجموعه؛) مشتری عمومی (نام رشته، بانک رشته): پایه (نام) (بانک = بانک؛))

در این سلسله مراتب کلاس، می‌توانیم زنجیره وراثت زیر را دنبال کنیم: Object (همه کلاس‌ها به طور ضمنی از نوع Object ارث می‌برند) -> Person -> Employee | Client.

علاوه بر این، در این سلسله مراتب کلاس، انواع پایه در بالا و انواع مشتق شده در پایین قرار دارند.

تحول بالادست. به روز رسانی

اشیاء از نوع مشتق شده (که در پایین سلسله مراتب است) نیز نوع پایه را نشان می دهند. برای مثال، شی Employee نیز یک شی از کلاس Person است. که در اصل طبیعی است، زیرا هر کارمند (کارمند) یک شخص (شخص) است. و برای مثال می توانیم اینگونه بنویسیم:

Static void Main (string args) (Employee works = کارمند جدید ("Tom"، "Microsoft"); Person person = کارمند؛ // تبدیل از Employee به Person Console.WriteLine (person.Name); Console.ReadKey (); )

در این حالت، به متغیر person که نشان دهنده نوع Person است، یک مرجع به شی Employee اختصاص داده می شود. با این حال، برای ذخیره یک مرجع به یک شی از یک کلاس در متغیری از کلاس دیگر، باید یک تبدیل نوع انجام دهید - در این مورد، از نوع Employee به نوع Person. و از آنجایی که Employee از کلاس Person ارث می برد، یک تبدیل ضمنی up-conversion به طور خودکار انجام می شود - تبدیل به انواعی که در بالای سلسله مراتب کلاس هستند، یعنی به کلاس پایه.

در نتیجه، متغیرهای staff و person به یک شی در حافظه اشاره می کنند، اما تنها بخشی که عملکرد نوع Person را نشان می دهد در دسترس متغیر شخص خواهد بود.

دیگر تبدیل‌های بالادستی به روشی مشابه انجام می‌شوند:

Person person2 = مشتری جدید ("باب"، "ContosoBank")؛ // تبدیل از مشتری به شخص

در اینجا، متغیر person2 که نوع Person را نشان می‌دهد، ارجاعی به شی Client دارد، بنابراین یک تبدیل ضمنی از پایین به بالا نیز از کلاس Client مشتق شده به نوع Person پایه انجام می‌شود.

تبدیل ضمنی رو به بالا نیز در موارد زیر رخ خواهد داد:

Object person1 = کارمند جدید ("Tom"، "Microsoft"); // Employee to object object person2 = new Client ("Bob", "ContosoBank"); // از Client به شی شی person3 = new Person ("Sam"); // شخص به اعتراض

از آنجایی که نوع شی برای همه انواع دیگر پایه است، تبدیل به آن به صورت خودکار انجام می شود.

تحولات نزولی پایین انداختن

اما علاوه بر تبدیل های بالادستی از نوع مشتق شده به مبنا، کاهش یا کاهش از نوع پایه به مشتق شده وجود دارد. به عنوان مثال، در کد زیر، متغیر person یک مرجع به شی Employee ذخیره می کند:

کارمند کارمند = کارمند جدید ("تام"، "مایکروسافت"); شخص شخص = کارمند; // تبدیل از Employee به Person

و ممکن است این سوال پیش بیاید که آیا امکان دسترسی به عملکرد نوع Employee از طریق متغیری از نوع Person وجود دارد؟ اما چنین تحولاتی به طور خودکار انجام نمی شود، زیرا هر شخص (شیء شخص) کارمند شرکت (شیء کارمند) نیست. و برای تبدیل رو به پایین، باید تبدیل‌های صریح را اعمال کنید، با مشخص کردن نوع داخل پرانتز که می‌خواهید به آن تبدیل کنید:

کارمند کارمند = کارمند جدید ("تام"، "مایکروسافت"); شخص شخص = کارمند; // تبدیل از Employee به Person // Employee staff2 = person; // این امکان پذیر نیست، شما نیاز به تغییر صریح دارید Employee staff2 = (Employee) person; // تبدیل از Person به Employee

بیایید به چند نمونه از تبدیل نگاه کنیم:

// شی Employee نیز از نوع object object obj = new Employee ("Bill", "Microsoft"); // برای دسترسی به قابلیت های نوع Employee، شی را به نوع Employee ارسال کنید Employee emp = (Employee) obj; // شی Client نیز نشان دهنده نوع Person Person person = new Client ("Sam", "ContosoBank"); // تبدیل از Person به Client Client Client = (Client) person;

در حالت اول، به متغیر obj یک مرجع به شی Employee اختصاص داده می شود، بنابراین می توانیم شی obj را به هر نوع که در سلسله مراتب کلاس بین شی type و Employee قرار دارد تبدیل کنیم.

اگر بخواهیم به برخی از خصوصیات یا متدهای منفرد یک شی مراجعه کنیم، دیگر نیازی نیست که شی تبدیل شده را به یک متغیر نسبت دهیم:

// شی Employee نیز از نوع object object obj = new Employee ("Bill", "Microsoft"); // فرستادن به Person برای فراخوانی Display ((Person) obj) .Display (); // یا بیشتر // ((کارمند) obj) .نمایش (); // برای دریافت ویژگی شرکت به Employee فرستاده شود string comp = ((Employee) obj) .Company;

در عین حال در تبدیل این نوع باید دقت شود. به عنوان مثال، در مورد زیر چه اتفاقی می افتد:

// شی Employee نیز از نوع object object obj = new Employee ("Bill", "Microsoft"); // برای دریافت ویژگی بانک رشته بانک = ((مشتری) obj) .Bank;

در این حالت با خطا مواجه خواهیم شد زیرا متغیر obj ارجاعی به شی Employee دارد. این شی نیز یک شی از انواع object و Person است، بنابراین می توانیم آن را به این نوع تبدیل کنیم. اما نمی توانیم به نوع Client تبدیل کنیم.

مثالی دیگر:

Employee emp = شخص جدید ("تام"); //! Error Person person = New Person ("Bob"); Employee emp2 = (Employee) person; //! خطا

در این حالت، ما سعی می کنیم یک شی از نوع Person را به نوع Employee تبدیل کنیم و شی Person یک شیء Employee نیست.

چندین راه برای جلوگیری از این خطاهای تبدیل وجود دارد.

روش های تبدیل

ابتدا می توان از کلمه کلیدی as استفاده کرد. با استفاده از آن، برنامه سعی می کند عبارت را بدون استثناء به یک نوع خاص تبدیل کند. در صورت تبدیل ناموفق، عبارت حاوی مقدار null خواهد بود:

شخص شخص = شخص جدید ("تام"); Employee emp = شخص به عنوان Employee; if (emp == null) (Console.WriteLine ("تبدیل انجام نشد")؛) other (Console.WriteLine (emp.Company)؛)

راه دوم گرفتن InvalidCastException است که در نتیجه تبدیل پرتاب می شود:

شخص شخص = شخص جدید ("تام"); امتحان کنید (Employee emp = (کارمند) شخص؛ Console.WriteLine (emp.Company)؛) catch (InvalidCastException ex) (Console.WriteLine (ex.Message)؛)

راه سوم آزمایش اعتبار تبدیل با استفاده از کلمه کلیدی is است:

شخص شخص = شخص جدید ("تام"); if (person is Employee) (Employee emp = (کارمند) شخص؛ Console.WriteLine (emp.Company)؛) other (Console.WriteLine ("بدون تبدیل مجاز نیست")؛)

عبارت person is Employee تست می کند که آیا متغیر person یک شی از نوع Employee است یا خیر. اما از آنجایی که در این مورد به وضوح اینطور نیست، پس چنین چکی نادرست برمی گردد و تبدیل کار نخواهد کرد.

مقالات مرتبط برتر