در برنامهنویسی بارها مواردی بهوجود میآید که یک نوع از یک متغیر را به نوع دیگری اختصاص دهید. بهعنوان مثال گاهی پیش میآید که مقدار یک int را به یک float اختصاص دهید.
در مواردی که عملیات ریاضی انجام میدهید، نتیجهی محاسبات از جنس متغیر شما خواهد بود. برای مثال هنگامیکه دو int را بر هم تقسیم میکنید، نتیجه از جنس int خواهد بود.
int i; double b; i = 180; b = i; // assing an int to a double
هنگامیکه دو نوع سازگار با هم ترکیب میشوند، مقدار سمت راست بهصورت اتوماتیک به نوع متغیر سمت چپ کانورت میشود. بنابراین در برنامه بالا، مقدار i ابتدا به double کانورت (تبدیل) شده و سپس به b اختصاص مییابد.
بهعلت سختگیری سیشارپ در بررسی نوع دادهها، هر نوع دادهای برای تبدیل شدن به نوع دیگر سازگار نیست و بهصورت اتوماتیک کانورت نمیشود که در این موارد برای کانورت میتوان از cast کردن استفاده کرد.
برای تبدیل نوع داده به نوع دیگر و کانورت کردن، دو روش موجود است:
- Implicit
- Explicit
در روش implicit تبدیل نوع بهصورت اتوماتیک اتفاق میافتد بهشرطیکه:
- هر دو نوع داده با هم سازگاری داشته باشند.
- بازه و محدودهی نوع مقصد بزرگتر از بازه و محدودهی نوع مبدا باشد.
هنگامیکه این دو شرط برقرار باشند تبدیل نوع بهصورت اتوماتیک (implicit) انجام میشود و به اصطلاح یک widening conversion اتفاق میافتد. بهعنوان مثال نوع int محدوده و بازهی کافی برای نگهداری نوع byte را در خود دارد. همچنین int و byte دو نوع سازگار هستند. بنابراین یک کانورت به روش implicit میتواند اتفاق افتد.
به مثال زیر توجه کنید:
using System; class Example { static void Main() { int i = 300; byte b = 255; /* It's a implicit conversion */ i = b; // assing a byte to an int Console.WriteLine("We assing a byte to an int: " + i); } }
در این مثال یک implicit conversion اتفاق میافتد زیرا هر دو شرط برای این تبدیل نوع برقرار است.
اگرچه برای اختصاص دادن byte به int کانورت بهصورت implicit اتفاق میفتد اما برای اختصاص دادن int به byte این اتفاق نمیافتد و به اصطلاح widening conversion ای در کار نیست زیرا یکی از آن دو شرط برایimplicit conversion نقض شده است (بازه و محدودهی نوع مقصد باید بزرگتر از بازه و محدودهی نوع مبدا باشد).
به مثال زیر که نادرست است و اجرا نمیشود توجه کنید:
using System; class Example { static void Main() { /* This program will not compile */ int i = 150; byte b; b = i; // Illegal!!! Console.WriteLine(b); } }
البته با یک تغییر کوچک برنامه بالا قابل اجرا خواهد بود که در ادامه به شرح آن میپردازیم. اگر توجه کرده باشید هنگام اجرای برنامه بالا این پیغام خطا را دریافت میکنید:
Connot implicitly convert type ‘int’ to ‘byte’. An explicit conversion exists (are you missing a cast?)
برای نوع دادههایی که با هم سازگاری ندارند و بهصورت implicit نمیتوانند کانورت شوند باید از از روش explicit و cast کردن استفاده کرد. در cast کردن ما به کامپایلر دستور میدهیم که نوع یک متغیر را آنطور و به آنچه که میخواهیم تبدیل کند (روش explicit).
فرم کلی cast کردن به شکل زیر است:
(target-type) expression
در اینجا، target-type مشخص کنندهی نوعی است که شما خواستهاید expression به آن تبدیل شود.
بهعنوان مثال:
double x, y;
اگر شما بخواهید که حاصل x / y از جنس int باشد میتوانید بنویسید:
(int) (x / y);
همانطور که میدانید x و y از جنس double هستند اما از طریق cast کردن حاصل آنها تبدیل به int شده است.
به این مثال توجه کنید:
using System; class Example { static void Main() { double x, y; x = 25.3; y = 5.1; int result = (int) (x / y); Console.WriteLine("The result is " + result); } }
در برنامه بالا x و y که هردو از جنس double هستند بر هم تقسیم شدهاند. حاصل این تقسیم مسلماً از جنس double خواهد بود اما ما از طریق cast کردن آن را به int تبدیل کردهایم. پرانتزهای اطراف x و y ضروری هستند زیرا در صورت نبود آنها تنها x به int تبدیل میشود.
در cast کردن اگر نوع متغیر مقصد کوچکتر از مبدا باشد ممکن است بخشی از اطلاعات از بین برود. همچنین هنگام cast کردن مقادیر اعشاری به عدد صحیح قسمت اعشاری آنها از بین میرود. برای مثال هنگام cast کردن مقدار 1.23 به عدد صحیح نتیجه 1 خواهد بود. همچنین هنگامیکه قصد دارید نوع int را در نوع byte قرار دهید مقداری از اطلاعات ممکن از از بین برود چراکه نهایت مقداری که byte میتواند ذخیره کند عدد 255 است:
using System; class Example { static void Main() { int anOkayInt = 345; byte aBadByte = (byte)anOkayInt; Console.WriteLine(aBadByte); } }
خروجی این برنامه عدد 89 است. اگر قصد داشته باشید عدد 256 را از طریق cast کردن در byteذخیره کنید، عددی که ذخیره میشود صفر است. اگر 257 را در byte ذخیره کنید، عدد 1 ذخیره میشود و همینطور که میبینید ذخیرهی عدد 345 در byte موجب شده تا عدد 89 در آن قرار گیرد که دقیقاً معادل تفریق 345 و 256 است.
به مثال زیر دقت کنید:
using System; class Exampe { static void Main() { double x, y; byte b; int i; char ch; uint u; short s; long l; x = 10.0; y = 3.0; // Cast double to int, fractional component lost. i = (int)(x / y); Console.WriteLine("Integer outcome of x / y: " + i); Console.WriteLine(); // Cast an int into a byte, no data lost. i = 255; b = (byte)i; Console.WriteLine("b after assigning 255: " + b + " -- no data lost."); // Cast an int into a byte, data lost. i = 257; b = (byte)i; Console.WriteLine("b after assigning 257: " + b + " -- data lost."); Console.WriteLine(); // Cast a uint into a short, no data lost. u = 32000; s = (short)u; Console.WriteLine("s after assigning 32000: " + s + " -- no data lost."); // Cast a uint into a short, data lost. u = 64000; s = (short)u; Console.WriteLine("s after assigning 64000: " + s + " -- data lost."); Console.WriteLine(); // Cast a long into a uint, no data lost. l = 64000; u = (uint)l; Console.WriteLine("u after assigning 64000: " + u + " -- no data lost."); // Cast a long into a uint, data lost. l = -12; u = (uint)l; Console.WriteLine("u after assigning -12: " + u + " -- data lost."); Console.WriteLine(); // Cast a byte into a char. b = 88; // ASCII code for X ch = (char)b; Console.WriteLine("ch after assigning 88: " + ch); } }
خروجی:
بهتر است هر قسمت این برنامه را شرح دهیم. در قسمت اول (x / y) به int تبدیل شده است. در اینجا قسمت اعشاری نتیجهی تقسیم از بین میرود. در قسمت بعد عدد صحیح 255 را به byte اختصاص دادهایم و به این علت که byte توانایی نگهداری این مقدار را دارد، هیچ اطلاعاتی از بین نمیرود اما با این حال به cast کردن نیاز است چراکه بهصورت implicit نمیتوان int را به byte کانورت کرد. در قسمت بعدتر 257 را به byte اختصاص دادهایم که موجب از بین رفتن اطلاعات میشود.
در بقیهی موارد نیز به همین شکل اتفاق میافتد. اگر متغیری که قرار است مقداری در آن ریخته شود، گنجایش کافی برای نگهداری از آن را داشته باشد هیچ اطلاعاتی از بین نخواهد رفت، در غیر این صورت بخشی از اطلاعات از بین میرود.
مهدی
23 November 2012
سلام بازم ممنون از آموزش خیلی خوبتون .اگه میشه بحث آرایه هارو هم مطرح کنید.ودر مورد ماتریس ها توضیح بدهید.
مسعود درویشیان
23 November 2012
سلام. مبحث آرایههای یک بعدی و دو بعدی در قسمتهای 17، 18 و 19 مورد بحث قرار میگیره
داوود
24 November 2012
با سلام خدمت شما آقای مهندس؛
دستتون درد نکنه بابت زحماتی که متحمل میشید.
چند سوال در اینجا برام پیش اومد؟
الف – بعنوان مثال اگه ما دو تا متغیر از نوع int و با مقادیر 7 و 3 داشته باشیم؛ و اونها رو بر همدیگه تقسیم کنیم، نتیجه اعشاری میشه، ولی چرا با اینکه اگه نتیجه رو از نوع int بگیریم ، برنامه ایرادی نمیگیره؟ بخاطر همون موضوعی که گفتید هست؟ یعنی چون نتیجه که اعشاری میشه از Int کوچیکتره و همنوع هم هستند؟ولی عکس این موضوع کار نمیکنه! یعنی اگه ما دو تا متغیر رو از نوع float بگیریم ونتیجه رو از نوع int برنامه خطا میگیره! آیا بدلیل هم نوع نبودنشونه؟ اگه اینجوری باشه پس اولی رو هم نباید جوا ب بده.
ب – جهت روشن تر شدن موضوع در مثال اول b=i ؛ مقصد در طرف چپ قرار داره دیگه درسته ؟
در این نوع عبارات مقصد همیشه در طرف چپ واقع شده؟
ج- میشه انواع نوعهای سازگار رو بگید؟
د- در این جدول http://msdn.microsoft.com/en-US/library/kca3w8x6%28v=vs.80%29.aspx
میشه گفت عمل casting (نوعهای سمت راست به نوعهای سمت چپ) به صورت implicit اتفاق میفته؟ یعنی نیازی به casting توسط ما نیست.
یا در این جدول این اتفاق میفته: http://msdn.microsoft.com/en-us/library/k1e94s7e%28v=vs.80%29.aspx
در واقع من میخوام 2 تا جدول داشته باشم که بدونم کدوم نوع رو در تبدیل به نوع دیگه نیاز به عمل casting دارم و کدوم نوع رو ندارم؟ (یعنی کدوم اتوماتیک انجام میشه و کدوم نه؟)
ببخشید که سوالات زیادی ازتون پرسیدم.امیدوارم بتونم منظورمو واضح رسونده باشم.
موفق باشید.
مسعود درویشیان
3 December 2012
نوعهایی که به صورت implicit تبدیل میشن رو براتون لیست کردم:
از sbyte به short ،int ،long ،float ،double ،decimal
از byte به short ،ushort ،int ،uint ،long ،ulong ،float ،double ،decimal
از short به int ،long ،float ،double ،decimal
از ushort به int ،uint ،long ،ulong، float، double ،decimal
از int به long ،float ،double ،decimal
از uint به long ،ulong ،float ،double ،decimal
از long به float ،double ،decimal
از ulong به float ،double ،decimal
از char به ushort ،int ،uint ،long ،ulong ،float ،double ،decimal
از float به double
در مورد انتساب ( مثلاً b = i) همیشه مقدار سمت راست توی مقدار سمت چپ ریخته میشه
s0m4y3h
27 November 2012
سلام
لطف ميكنيد سري فيبوناچي رو بنويسيد چطوري ميشه ساخت ؟
و اعداد مركب رو همين طور
ممنون ميشم
جدا
ببخشيد
شرمنده
رضا
11 December 2013
بسیار سپاسگزارم بابت توضیحات ارزنده شما.
سلام
10 August 2015
سلام ببخشید اگر ما short را به byteتبدیل کنیم و عدد ما2200 برای مثال باشد چرا وقتی تبدیل میشه عدد 152 رو چاپ میکنه
hosein
21 October 2015
با سلام.
از اموزش های خوبتون واقعا ممنونم.
من بیشتر چیز هایی که یاد گرفتم از سایت خوب شما بوده .
واقعا عالیه
هانا
15 October 2017
وای فوق العاده اس من ازاول خوندم والان ای پارت ام ایشالا روز به روز درخشان تراز وموفق ترباشید خواستم حالا که مطالبتون رو میخونم تشکر کرده باشم
حسین بنیادی
13 December 2017
سلام مهندس خسته نباشید من یه سوال داشتم من کد زیر رو ک تو آموزش بود رو نوشتم ولی شما گفتید مقدار بایت تا 255 بیشتر تبدیل نمیشه چرا در جواب این کد دقیقا عدد 560 رو نشون میده میشه بگید چه اتفاقی افتاده من یخورده گیج شدم؟
[css]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication8
{
class Program
{
static void Main(string[] args)
{
int anOkayint = 560;
byte aBadbyte = (byte)anOkayint;
Console.WriteLine(anOkayint);
}
}
}
[css/]