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

عملیات ریاضی c#. عبارات شرطی

عملگرهای رابطه ای و منطقی

در علامت گذاری عملگر رابطهو عملگر منطقیمدت، اصطلاح روابطبه معنای رابطه ای است که می تواند بین دو معنی و اصطلاح وجود داشته باشد منطقی- رابطه بین مقادیر منطقی "درست" و "نادرست". و از آنجایی که عملگرهای رابطه ای نتایج درست یا نادرست تولید می کنند، اغلب به همراه عملگرهای منطقی استفاده می شوند. به همین دلیل است که آنها را با هم در نظر می گیرند.

عملگرهای رابطه ای زیر هستند:

عملگرهای بولی شامل موارد زیر است:

نتیجه اجرای یک عملگر رابطه ای یا منطقی یک مقدار بولی از نوع bool است.

به طور کلی، اشیاء را می توان برای برابری یا نابرابری با استفاده از عملگرهای رابطه ای == و != مقایسه کرد. و عملگرهای مقایسه، =، فقط می توانند برای انواع داده ای اعمال شوند که از یک رابطه سفارش پشتیبانی می کنند. بنابراین، عملگرهای رابطه ای را می توان برای تمام انواع داده های عددی اعمال کرد. اما مقادیر bool را فقط می توان برای برابری یا نابرابری مقایسه کرد، زیرا مقادیر true (true) و false (false) مرتب نمی شوند. به عنوان مثال، مقایسه true > false در سی شارپ منطقی نیست.

یک نمونه برنامه را در نظر بگیرید که استفاده از عملگرهای رابطه ای و منطقی را نشان می دهد:

استفاده از سیستم؛ با استفاده از System.Collections.Generic. با استفاده از System.Linq؛ با استفاده از System.Text. namespace ConsoleApplication1 ( کلاس Program ( استاتیک void Main(string args) ( short d = 10, f = 12; bool var1 = true, var2 = false; if (d f) Console.WriteLine("d > f"); // مقایسه متغیرهای var1 و var2 if (var1 & var2) Console.WriteLine("این متن خروجی نخواهد شد")؛ if (!(var1 & var2)) Console.WriteLine("!(var1 & var2) = true")؛ اگر (var1 | var2) Console.WriteLine("var1 | var2 = true"); if (var1 ^ var2) Console.WriteLine("var1 ^ var2 = true"); Console.ReadLine(); ) )

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

عملیات ضمنی را می توان بر اساس ترکیبی از عملگرهای منطقی ساخت! و |:

میانبر عملگرهای بولی

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

یک عملیات AND منطقی کوتاه شده با استفاده از آن انجام می شود اپراتور &&و عملیات منطقی کوتاه شده OR - using اپراتور ||. این عملگرهای منطقی کوتاه شده با عملگرهای منطقی معمولی & و | مطابقت دارند. تنها تفاوت بین یک عملگر منطقی کوتاه شده و یک عملگر معمولی این است که عملوند دوم آن فقط در صورت نیاز ارزیابی می شود.

آخرین به روز رسانی: 1396/06/19

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

عملیات حسابی باینری:

    عملیات جمع دو عدد:

    int x = 10; int z = x + 12; // 22

    عمل تفریق دو عدد:

    int x = 10; int z = x - 6; // چهار

    عمل ضرب دو عدد:

    int x = 10; int z = x * 5; // پنجاه

    عمل تقسیم دو عدد:

    int x = 10; int z = x / 5; // 2 دو برابر a = 10; دو برابر b = 3; دو برابر c = a / b; // 3.33333333

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

    z دو برابر = 10 / 4; //نتیجه 2 است

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

    برای برون رفت از این وضعیت، لازم است لفظ یا متغیرهای درگیر در عملیات دقیقاً به صورت دو یا شناور تعریف شوند:

    دابل z = 10.0 / 4.0; //نتیجه 2.5 است

    عملیات دریافت موجودی از تقسیم عدد صحیحدو عدد:

    دو برابر x = 10.0; دو برابر z = x % 4.0; //نتیجه 2 است

تعدادی نیز وجود دارد عملیات واحد، که در آن یک عملوند شرکت می کند:

    عملیات افزایشی

    این افزایش می تواند پیشوند شود: ++x - ابتدا مقدار x با 1 افزایش می یابد و سپس مقدار آن به عنوان نتیجه عملیات برگردانده می شود.

    و همچنین یک افزایش پسوند وجود دارد: x++ - ابتدا مقدار x به عنوان نتیجه عملیات برگردانده می شود و سپس 1 به آن اضافه می شود.

int x1 = 5; intz1 = ++x1; // z1=6; x1=6 Console.WriteLine($"(x1) - (z1)"); int x2 = 5; intz2 = x2++; // z2=5; x2=6 Console.WriteLine($"(x2) - (z2)");

عملیات کاهش یا کاهش یک مقدار. همچنین یک فرم پیشوند کاهش (--x) و یک فرم پسوند (x--) وجود دارد.

int x1 = 5; intz1 = --x1; // z1=4; x1=4 Console.WriteLine($"(x1) - (z1)"); int x2 = 5; intz2 = x2--; // z2=5; x2=4 Console.WriteLine($"(x2) - (z2)");

هنگام انجام چندین عملیات حسابی به طور همزمان باید ترتیب اجرای آنها را در نظر گرفت. اولویت عملیات از بالاترین به پایین ترین:

    افزایش، کاهش

    ضرب، تقسیم، باقیمانده

    جمع، تفریق

از پرانتز برای تغییر ترتیب عملیات استفاده می شود.

مجموعه ای از عملیات را در نظر بگیرید:

Int a = 3; int b = 5; int c = 40; int d = c---b*a; // a=3 b=5 c=39 d=25 Console.WriteLine($"a=(a) b=(b) c=(c) d=(d)");

در اینجا با سه عمل کاهش، تفریق و ضرب سروکار داریم. ابتدا متغیر c کاهش می یابد، سپس ضرب b*a و در نهایت تفریق می شود. یعنی در واقع مجموعه عملیات به این صورت بود:

Int d = (c--)-(b*a);

اما با پرانتز می‌توانیم ترتیب عملیات را به‌طور مثال به صورت زیر تغییر دهیم:

Int a = 3; int b = 5; int c = 40; int d = (c-(--b))*a; // a=3 b=4 c=40 d=108 Console.WriteLine($"a=(a) b=(b) c=(c) d=(d)");

انجمن اپراتور

همانطور که در بالا ذکر شد، عملیات ضرب و تقسیم دارای اولویت یکسانی هستند، اما نتیجه در عبارت:

int x = 10 / 5 * 2;

آیا باید این عبارت را به صورت (10 / 5) * 2 یا 10 / (5 * 2) تفسیر کنیم؟ پس از همه، بسته به تفسیر، نتایج متفاوتی می گیریم.

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

    عملگرهای انجمنی چپ که از چپ به راست اجرا می شوند

    عملگرهای ارتباطی راست که از راست به چپ اجرا می شوند

همه عملگرهای حسابی(به جز افزایش و کاهش پیشوند) چپ انجمنی هستند، یعنی از چپ به راست اجرا می شوند. بنابراین، عبارت 10 / 5 * 2 باید به صورت (10 / 5) * 2 تفسیر شود، یعنی نتیجه 4 خواهد بود.

هیچ تبدیل بولی ضمنی در سی شارپ وجود ندارد، حتی برای انواع حسابی اعداد صحیح. بنابراین، یک ورودی کاملاً صحیح در زبان C++ این است:

بین المللیک1 = 7;
اگر (ک1) کنسول. خط بنویس(" خوب!");

غیر قانونی در برنامه های سی شارپ در مرحله ترجمه خطایی رخ می دهد زیرا شرط ارزیابی شده از نوع است بین المللی, و تبدیل ضمنی این نوع به تایپ بوولگم شده

در سی شارپ قوانین سختگیرانه تری برای عملیات منطقی نیز اعمال می شود. بله، ضبط کنید اگر(ک1 && (ایکس> y)), درست در C++، منجر به خطا در

برنامه های C# زیرا عملگر && فقط برای عملوندهای نوع تعریف شده است بوول, و در این عبارت یکی از عملوندها دارای نوع است بین المللی. در زبان سی شارپ در این مواقع باید از نماد استفاده کنید:

اگر(ک1>0)
اگر((ک1>0) && (ایکس> y))

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

/// < خلاصه>
/// عبارات بولی
/// خلاصه>
عمومیخالیمنطق() {
// عملیات نفی ~، !
bool b1, b2;
b1= 2*2 == 4;
b2= !b1;
//b2= ~b1;
uint j1= 7, j2;
j2= ~j1;
//j2= !j1;
int j4= 7, j5;
j5= ~j4;
Console.WriteLine("uint j2= " + j2+ " int j5= " + j5)؛
} // منطق

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

unintj2 = 4294967288
بین المللیj5 = -8.

عملیات منطقی باینری " && - مشروط و "و" || - شرطی OR" فقط بر روی نوع داده تعریف می شوند بوول. عملیات شرطی یا کوتاه نامیده می شوند زیرا ارزیابی عملوند دوم به مقدار عملوند اولی که قبلاً ارزیابی شده است بستگی دارد. ارزش عملیات بولی شرطی در کارایی آنها در زمان اجرا نهفته است. اغلب آنها به شما اجازه محاسبه می دهند بیان بولی A که منطقی است، اما در جایی که عملوند دوم تعریف نشده است. بیایید به عنوان مثال مشکل کلاسیک جستجوی یک الگو در یک آرایه را در نظر بگیریم، زمانی که عنصری با مقدار معین (الگو) جستجو می‌شود. ممکن است چنین عنصری در آرایه وجود داشته باشد یا نباشد. در اینجا یک راه حل معمولی برای این مشکل به شکل ساده شده است، اما ماهیت موضوع را بیان می کند:

// مشروطو- &&
بین[] ar= { 1, 2, 3 };
جستجوی بین المللی= 7;
int i= 0;
در حالی که ((< ar.Length)&& (ar[i]!= جستجو کردن)){
i++;
}
اگر من< ar.Length)Console.WriteLine("نمونهیافت");
دیگرConsole.WriteLine("نمونهنهیافت");

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

سه باینری عملیات بیتی- «& - AND» ، « | - OR، "^ - XOR" به دو صورت استفاده می شود. آنها به عنوان انواع اعداد صحیح بالا تعریف شده اند بین المللی, و بیش از انواع Boolean. در مورد اول آنها به عنوان عملیات بیتی استفاده می شوند، در مورد دوم به عنوان عملیات منطقی معمولی استفاده می شوند. گاهی اوقات لازم است که هر دو عملوند به هر حال ارزیابی شوند، پس این عملیات ضروری هستند. در اینجا نمونه ای از اولین استفاده آنها آورده شده است:

//عملیات بیتی منطقیو, یا, XOR(&,|,^)
int k2= 7, k3= 5, k4، k5، k6;
k4= k2& k3;
k5= k2 | k3;
k6= k2^k3;
Console.WriteLine("k4= " + k4+ " k5= " + k5+ " k6= " + k6)؛

نتایج خروجی:

ک4 = 5 ک5 = 7 ک6 =2

در اینجا نمونه ای از تطبیق الگو با استفاده از AND منطقی آورده شده است: من= 0;

جستجو کردن= ar;
در حالی که ((< ar.Length)& (ar[i]!= جستجو)) i++;
اگر من< ar.Length)Console.WriteLine("نمونهیافت");
دیگری جConsole.WriteLine("نمونهنهیافت");

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

این بخش به طور خلاصه نحو و کاربرد تمام عملیات C# را توضیح می دهد، به جز برخی از عملیات های اولیه که بعداً در مطالب مربوطه پوشش داده می شوند.

افزایش و کاهش

عملگرهای افزایش (++) و کاهش (--) عملوند را یک عدد افزایش و کاهش می دهند. آنها دو شکل دارند - پیشوندوقتی علامت عملیات قبل از عملوند نوشته می شود و پسوند. در فرم پیشوند ابتدا عملوند تغییر می کند و سپس مقدار آن به مقدار حاصل از عبارت تبدیل می شود، در حالی که در فرم پسوند، مقدار عبارت مقدار اصلی عملوند است و پس از آن تغییر می کند.

عملیات استانداردافزایش برای مقادیر صحیح، نمادین، واقعی و مالی وجود دارد.

عملیات جدید

عملگر new برای ایجاد یک شی جدید استفاده می شود. فرمت عملیات:

نوع جدید ([ آرگومان ها ])

با این عملیات، می توانید اشیایی از هر دو نوع مرجع و مقدار ایجاد کنید، به عنوان مثال:

شی z = شیء جدید(); int i = new int(); // مانند int i = 0;

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

عملیات نفی

نفی حسابی(یک واحد منهای - ) علامت عملوند را معکوس می کند. عملگر نفی استاندارد برای انواع int , long , float , double و decimal تعریف شده است . در صورت امکان می توان آن را در مقادیری از انواع دیگر نیز اعمال کرد. تبدیل ضمنیبه این انواع

بولی نفی(!) برای نوع bool تعریف شده است. اگر عملوند درست باشد نتیجه عمل نادرست است و اگر عملوند نادرست باشد درست است.

نفی بیتی(~) که اغلب به آن بیتی می گویند، هر بیت را در نمایش دودویی یک عملوند از نوع int، uint، طولانی یا ulong معکوس می کند.

تبدیل نوع صریح

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

(نوع) بیان

در اینجا type نام نوعی است که تبدیل به آن انجام می شود و عبارت اغلب نام یک متغیر است، به عنوان مثال:

طولانی b = 300; int a = (int) b; // داده ها از بین نمی روند int d = (بایت) a; // داده ها از بین می روند

ضرب، تقسیم و باقیمانده تقسیم

عملیات ضرب(*) حاصل ضرب دو عملوند را برمی گرداند. عملیات ضرب استاندارد برای انواع int , uint , long , ulong , float , double و decimal تعریف شده است . در صورتی که تبدیل ضمنی به این انواع برای آنها امکان پذیر باشد، می تواند برای مقادیر انواع دیگر اعمال شود. نوع نتیجه عملیات برابر با "بزرگترین" نوع عملوندها است، اما کمتر از int نیست.

جدول 3.2. نمادهای x و y مقادیر مثبت نهایی را نشان می دهند، نماد z نتیجه عملیات ضرب واقعی است. اگر نتیجه برای نشان دادن آن خیلی بزرگ است نوع داده شده، برابر با مقدار "بی نهایت" در نظر گرفته می شود، اگر خیلی کوچک باشد، 0 در نظر گرفته می شود. NaN (نه یک عدد) به این معنی است که نتیجه یک عدد نیست.

جدول 3.2. نتایج ضرب واقعی
* +y -y +0 -0 + - NaN
+x +z -z +0 -0 + - NaN
-ایکس -z +z -0 +0 - + NaN
+0 +0 -0 +0 -0 NaN NaN NaN
-0 -0 +0 -0 +0 NaN NaN NaN
+ + - NaN NaN + - NaN
- - + NaN NaN - + NaN
NaN NaN NaN NaN NaN NaN NaN NaN

عملیات تقسیم(/ ) ضریب تقسیم عملوند اول بر دوم را محاسبه می کند. عملگر تقسیم استاندارد برای انواع int , uint , long , ulong , float , double و decimal تعریف شده است . اگر تبدیل ضمنی به این انواع برای آنها وجود داشته باشد، می تواند برای مقادیر انواع دیگر اعمال شود. نوع نتیجه توسط قوانین تبدیل تعیین می شود، اما نه کمتر از int.

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

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

جدول 3.3. نتایج تقسیم واقعی
/ +y -y +0 -0 + - NaN
+x +z -z + - +0 -0 NaN
-ایکس -z +z - + -0 +0 NaN
+0 +0 -0 NaN NaN +0 -0 NaN
-0 -0 +0 NaN NaN -0 +0 NaN
+ + - + - NaN NaN NaN
- - + - + NaN NaN NaN
NaN NaN NaN NaN NaN NaN NaN NaN

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

عملیات باقی مانده از بخش(٪ ) نیز برای مقادیر صحیح، واقعی و مالی به طور متفاوتی تفسیر می شود. اگر هر دو عملوند اعداد صحیح باشند، نتیجه عملیات x - (x / y) * y است. اگر مقسوم علیه صفر باشد، یک System.DivideByZeroException پرتاب می شود.

اگر حداقل یکی از عملوندها واقعی باشد، نتیجه عملیات با فرمول x - n * y محاسبه می شود، که در آن n بزرگترین عدد صحیح کوچکتر یا مساوی با نتیجه تقسیم x بر y است. تمام ترکیبات ممکن از مقادیر عملوند در جدول 3.4 نشان داده شده است.

جدول 3.4. نتایج واقعی باقی مانده
% +y -y +0 -0 + - NaN
+x +z z NaN NaN ایکس ایکس NaN
-ایکس -z -z NaN NaN -ایکس -ایکس NaN
+0 +0 +0 NaN NaN +0 +0 NaN
-0 -0 -0 NaN NaN -0 -0 NaN
+ NaN NaN NaN NaN NaN NaN NaN
- NaN NaN NaN NaN NaN NaN NaN
NaN NaN NaN NaN NaN NaN NaN NaN

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

جمع و تفریق

عملیات اضافه(+) مجموع دو عملوند را برمی گرداند. عملیات جمع استاندارد برای انواع int , uint , long , ulong , float , double و اعشاری تعریف شده است . اگر تبدیل ضمنی به این انواع برای آنها وجود داشته باشد، می تواند برای مقادیر انواع دیگر اعمال شود. نوع نتیجه عملیات برابر با "بزرگترین" نوع عملوندها است، اما کمتر از int نیست.

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

جدول 3.5. نتایج اضافه واقعی
+ y +0 -0 + - NaN
ایکس z ایکس ایکس + - NaN
+0 y +0 +0 + - NaN
-0 y +0 -0 + - NaN
+ + + + + NaN NaN
- - - - NaN - NaN
NaN NaN NaN NaN NaN NaN NaN

عملیات تفریق(-) اختلاف دو عملوند را برمی گرداند. عمل تفریق استاندارد برای انواع int , uint , long , ulong , float , double و اعشاری تعریف شده است . اگر تبدیل ضمنی به این انواع برای آنها وجود داشته باشد، می تواند برای مقادیر انواع دیگر اعمال شود. نوع نتیجه عملیات برابر با "بزرگترین" نوع عملوندها است، اما کمتر از int نیست.

اگر هر دو عملوند صحیح یا اعشاری باشند و نتیجه عملیات آنقدر بزرگ باشد که با نوع داده شده نمایش داده نشود، یک System.OverflowException پرتاب می شود.

تمام مقادیر حاصل از تفریق ممکن برای عملوندهای واقعی در جدول 3.6 نشان داده شده است. نمادهای x و y مقادیر مثبت نهایی را نشان می دهند، نماد z نشان دهنده نتیجه یک عمل تفریق واقعی است. اگر x و y برابر باشند، نتیجه مثبت صفر است. اگر نتیجه خیلی بزرگ باشد که نمی‌توان آن را با نوع داده شده نشان داد، به عنوان مقدار «بی‌نهایت» با همان علامت x - y در نظر گرفته می‌شود، اگر خیلی کوچک باشد، با همان علامت x - y 0 در نظر گرفته می‌شود.

جدول 3.6. نتایج تفریق واقعی
- y +0 -0 + - NaN
ایکس z ایکس ایکس - + NaN
+0 -y +0 +0 - + NaN
-0 -y -0 +0 - + NaN
+ + + + NaN + NaN
- - - - - NaN NaN
NaN NaN NaN NaN NaN NaN NaN

عملیات شیفت

عملیات شیفت (<< и >> ) برای عملوندهای عدد صحیح اعمال می شود. آنها نمایش دودویی عملوند اول را با تعداد بیت های مشخص شده توسط عملوند دوم به چپ یا راست تغییر می دهند.

در تغییر مکان به چپ (<< ) освободившиеся разряды обнуляются. При تغییر سمت راست(>> ) اگر اولین عملوند از نوع بدون علامت باشد، بیت های آزاد شده با صفر و در غیر این صورت با بیت علامت دار پر می شوند. عملیات تعویض استاندارد برای انواع int , uint , long و ulong تعریف شده است.

عملیات رابطه ای و آزمون های برابری

عملیات رابطه (< , <= , >, >= , == , != ) عملوند اول را با دومی مقایسه کنید. عملگرها باید باشند نوع حسابی. نتیجه عملیات - نوع بولی، درست است یا نادرست. قوانین محاسبه نتایج در > y آورده شده است

درست است اگر x بزرگتر از y باشد، در غیر این صورت نادرست است ایکس<= y درست است اگر x کمتر یا مساوی y باشد، در غیر این صورت نادرست است x >= y درست است اگر x بزرگتر یا مساوی y باشد، در غیر این صورت نادرست است

عملیات منطقی بیتی

عملیات منطقی بیتی(& , | , ^ ) روی عملوندهای عدد صحیح اعمال می شوند و روی آنها عمل می کنند نمایش های باینری. هنگام انجام عملیات، عملوندها ذره ذره مطابقت داده می شوند (بیت اول عملوند اول با بیت اول دوم، بیت دوم عملوند اول با بیت دوم دوم و غیره). عملیات استاندارد برای انواع int , uint , long و ulong تعریف شده است.

در ربط بیتی(&)، بیت نتیجه فقط زمانی 1 است که بیت های متناظر هر دو عملوند 1 باشند.

در تفکیک بیتی(|)، بیت نتیجه 1 است اگر بیت متناظر حداقل یکی از عملوندها 1 باشد.

با XOR بیتی() بیت حاصل فقط زمانی 1 است که بیت متناظر تنها یکی از عملوندها 1 باشد.

عملیات منطقی مشروط

عملیات منطقی مشروطهر دو (&&) و OR (||) بیشتر با عملوندهای نوع بولی استفاده می شوند. نتیجه عملیات منطقی true است، سپس نتیجه عملیات شرطی مقدار عملوند دوم خواهد بود، در غیر این صورت مقدار عملوند سوم خواهد بود. یا عملوند دوم یا سوم همیشه ارزیابی می شود. نوع آنها ممکن است متفاوت باشد.

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

عملیات واگذاری

عملیات واگذاری(=، +=، -=، *=، و غیره) یک مقدار جدید برای متغیر تعریف می کند. این عملیات را می توان در برنامه به عنوان دستورات کامل استفاده کرد.

فرمت عملیات تکلیف ساده (= ):

متغیر = بیان

مکانیسم انجام عملیات انتساب به شرح زیر است: عبارت مورد ارزیابی قرار می گیرد و نتیجه آن در آدرسی در حافظه ذخیره می شود که با نام متغیر واقع در سمت چپ علامت عملیات تعیین می شود. آنچه قبلاً در این قسمت حافظه ذخیره شده بود از بین می رود. نمونه هایی از عملگرهای انتساب:

علاوه بر انتساب، عملوند اول به عملوند دوم اضافه می‌شود و نتیجه به عملوند اول نوشته می‌شود، یعنی عبارت a += b نماد فشرده‌تری از عبارت a = a + b است.

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

عملیات واگذاری راست انجمنی، یعنی برخلاف اکثر عملیات های دیگر از راست به چپ انجام می شوند (a = b = c به معنای a = (b = c) ).

سوالات و وظایف برای کار مستقل دانش آموز

  1. کجا می توان متغیرها را اعلام کرد؟ چه چیزی در اعلان یک متغیر گنجانده شده است؟
  2. وقتی عملوندها در یک عبارت استفاده می شوند چه اتفاقی می افتد انواع مختلف? مثال بزن.
  3. عملیات زبان سی شارپ را فهرست کنید و آنها را بر اساس اولویت گروه بندی کنید.
  4. NaN چیست؟ نتیجه کدام عملیات NaN است؟
  5. عملیات شیفت برای چه نوع عملوندهایی قابل استفاده است؟
  6. استثناها چیست؟
  7. اصول رسیدگی به استثنا را شرح دهید.

فصل 10 عبارات و عملگرها

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

اپراتورها

عملگر نمادی است که عملیاتی را که باید روی یک یا چند آرگومان انجام شود را نشان می دهد. هنگامی که دستور اجرا می شود، نتیجه به دست می آید. سینتکس اعمال عملگرها تا حدودی با روش های فراخوانی متفاوت است و باید فرمت عبارات حاوی عملگرها در سی شارپ را مانند پشت دست خود بدانید. مانند بسیاری از زبان‌های دیگر، معناشناسی عملگرها در سی شارپ از قوانین و نشانه‌هایی که از مدرسه برای ما آشنا بود پیروی می‌کند. اپراتورهای پایهدر سی شارپ شامل ضرب (*)، تقسیم (/)، جمع و به علاوه یکنفره (+)، تفریق و منهای یکنفره (-)، مدول (%) و تخصیص (=) است.

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

کلاس NoResultApp

{

public static void Main()

{

int i; int j;

i+j; // خطا به دلیل اینکه نتیجه به چیزی اختصاص داده نشده است. ) >

اکثر اپراتورها فقط روی انواع داده های عددی کار می کنند، مانند بایت، کوتاه، بلند، عدد صحیح، تک، دوتاییو اعشاری.استثنا عملگرهای مقایسه (== و !=) هستند. همچنین در سی شارپ می توانید از عملگرهای + و - در یک کلاس استفاده کنید رشتهو حتی از عملگرهای افزایشی (++) و (-) برای ساختارهای زبان غیرمعمول به عنوان نماینده استفاده کنید. در فصل 14 در مورد دوم بحث خواهم کرد.

تقدم اپراتور

هنگامی که چندین دستور در یک عبارت وجود دارد، کامپایلر باید ترتیب اجرای آنها را تعیین کند. در انجام این کار، کامپایلر توسط قوانینی هدایت می شود که نامیده می شوند تقدم عملگردرک تقدم عملگر ضروری است املای صحیحعبارات - گاهی اوقات ممکن است نتیجه آنطور که انتظار می رود نباشد.

عبارت 42 + 6 * 10 را در نظر بگیرید. اگر 42 و 6 را جمع کنید و سپس مجموع را در 10 ضرب کنید، عدد 480 به دست می آید. یک جزء خاص از کامپایلر است تحلیلگر واژگانی -مسئولیت ترتیب خواندن این کد را بر عهده دارد. این تحلیلگر واژگانی است که اولویت نسبی عملگرهای ناهمگن را در یک عبارت تعیین می کند. برای انجام این کار، از مقداری - اولویت - هر اپراتور پشتیبانی شده استفاده می کند. عملگرهای اولویت بالاتر ابتدا حل می شوند. در مثال ما، عملگر * بر عملگر + اولویت دارد زیرا * جذب می کند(حالا این اصطلاح را توضیح می دهم) عملوندهای آن قبل از + انجام می دهد. توضیح در قواعد حسابی کلی نهفته است: ضرب و تقسیم همیشهاولویت بیشتری نسبت به جمع و تفریق دارند. برگردیم به مثال: می گویند عدد 6 جذب شده استعملگر * و در 42 + 6 * 10 و در 42 * 6 + 10، بنابراین این عبارات معادل 42 + (6 * 10) و (42 * 6) + 10 هستند.

چگونه اولویت در سی شارپ تعیین می شود

حالا بیایید ببینیم اولویت عملگر در سی شارپ چگونه تعریف می شود. عملگرها در زیر به ترتیب تقدم نزولی فهرست شده اند (جدول 10-1). در مرحله بعد، من به جزئیات بیشتری در مورد دسته های مختلف اپراتورهای پشتیبانی شده در سی شارپ خواهم پرداخت.

Tab. 10-1.تقدم عملگر در سی شارپ.

دسته اپراتور اپراتورها
ساده (x)، x.y، f(x)، a[x]، x++، x -، جدید، نوع، اندازه، علامت‌گذاری شده، علامت‌نخورده
یگانه +، -، !، ++x، - x، (T)x
ضربی *,/, %
افزودنی +, -
تغییر مکان «, »
نگرش <, >, <=, >=، است
برابری ==
منطقی و (AND) &
منطقی انحصاری OR (XOR) ^
منطقی یا (OR) 1
شرطی و (AND) &&
IL AND مشروط (OR) II
وضعیت 9-
وظیفه = *= /= % = , + = , -= « = , » = , &=, ^ = , =

انجمن چپ و راست

Associativity تعیین می کند که کدام قسمت از عبارت ابتدا باید ارزیابی شود. به عنوان مثال، نتیجه عبارت بالا ممکن است 21 یا 33 باشد، بسته به اینکه کدام ارتباط برای عملگر "-" اعمال می شود: چپ یا راست.

عملگر - تداعی چپ می شود، یعنی ابتدا 42-15 محاسبه می شود و سپس 6 از نتیجه کم می شود. اگر ارتباط راست داشت، ابتدا سمت راست عبارت (15-6) ارزیابی می شود و سپس نتیجه از 42 کم می شود.

همه عملگرهای باینری (عملگرهایی با دو عملوند)، به جز عملگرهای انتساب، - چپ انجمنی،یعنی عبارات را از چپ به راست پردازش می کنند. به این ترتیب، a + b+ با -همان (الف + ب) + ج،جایی که برای اولین بار محاسبه می شود a + b،و سپس به جمع اضافه می شود با.اپراتورهای واگذاری و عبارات مشروط - راست انجمنی،یعنی عبارات را از راست به چپ پردازش می کنند. به عبارت دیگر، a=b=cمعادل با a = (ب= با).بسیاری از افراد زمانی که می خواهند چندین دستور انتساب را در یک خط قرار دهند به این موضوع دچار می شوند، بنابراین بیایید به این کد نگاه کنیم:

با استفاده از سیستم؛

کلاس RightAssocApp(

public static void Main() (

int a = 1; int b = 2; int c = 3;

Console.WriteLine("a=(0) b=(1) c=(2>"، a, b, c); a = b = c;

Console.WriteLine("بعد از "a=b=c - : a=(0) b=(1) c=(2)"، a, b, c); > >

نتیجه اجرای این مثال:

a=1 b=2 c=3

بعد از "a=b=c": a=3 b=3 o=3

ارزیابی عبارات از راست به چپ در ابتدا ممکن است گیج کننده باشد، اما بیایید به این روش نگاه کنیم: اگر عملگر انتساب چپ انجمن بود، کامپایلر ابتدا باید ارزیابی کند. a = b،سپس آمی شود 2 و سپس ب= با و در نتیجه بمی شود 3. نتیجه نهایی خواهد بود a=2 b=3 c=3.بدیهی است که هنگام نوشتن این چیزی نیست که ما انتظار داریم آ= ب= با،و به همین دلیل است که عملگرهای انتساب و عملگرهای شرطی حق انجمن هستند.

استفاده عملی

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

a \u003d b * c + d;

این رویکرد اساساً اشتباه است: کامپایلر نمی‌تواند به درستی کد را تجزیه کند اگر یک نحو خاص تعریف نشده باشد. کامپایلر کدها را طبق قوانین تعریف شده توسط توسعه دهندگان کامپایلر تجزیه و تحلیل می کند. از سوی دیگر، وجود دارد براکت های گرد، برای نشان دادن صریح تقدم و تداعی استفاده می شود. مثلاً عبارت آ= b * c + dرا می توان به صورت بازنویسی کرد a \u003d (b * c) + dیا چگونه آ= b * (c + d)و کامپایلر ابتدا عبارت پرانتز شده را ارزیابی می کند. اگر چند جفت پرانتز وجود داشته باشد، کامپایلر ابتدا عبارات داخل پرانتز و سپس کل عبارت را بر اساس قوانین تقدم و تداعی توصیف شده ارزیابی می کند.

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

اپراتورهای سی شارپ

بهتر است عملگرها را بر اساس اولویت در نظر بگیرید. در زیر رایج ترین اپراتورها را شرح خواهم داد.

اپراتورهای ساده

  • (x) این یک تغییر از عملگر پرانتز برای کنترل ترتیب ارزیابی هم در عملیات ریاضی و هم در فراخوانی روش است.
  • x.y عملگر نقطه برای تعیین عضوی از یک کلاس یا ساختار استفاده می شود. اینجا ایکسنشان دهنده موجودیت حاوی عضو است y
  • f(x) این نوع عملگر پرانتز برای شمارش آرگومان های متد استفاده می شود.
  • اوه] براکت های مربعیبرای نمایه سازی یک آرایه استفاده می شود. این براکت ها همچنین در رابطه با نمایه سازها زمانی که اشیا را می توان به عنوان یک آرایه در نظر گرفت استفاده می شود. برای نمایه سازها به فصل 7 مراجعه کنید.
  • x++ در بخش "عملگرهای افزایش و کاهش" به طور جداگانه در مورد عملگر افزایش صحبت خواهیم کرد.
  • x- عملگر کاهش نیز بعداً مورد بحث قرار خواهد گرفت.
  • new این عملگر برای ایجاد نمونه های شی بر اساس تعریف کلاس استفاده می شود.

نوعی از

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

با استفاده از سیستم؛

با استفاده از System.Reflection.

کلاس عمومی اپل(

عمومی int nSeeds;

public void Ripen()

{

> >

کلاس عمومی TypeOfApp(

public static void Main() (

Typet = typeof(Apple);

string className = t.ToStringO;

Console.IgShipe("\nاطلاعات کلاس 0 (O)", className);

Console.WriteLine("\nMeroflH (0)", className); کنسول. WriteLine ("--------"); روشهای MethodInfo = t.GetMethodsO;

foreach (روش MethodInfo در متدها)

Console.WriteLine(method.ToString());

}

Console.WriteLine("\nBce Members (O)", className); کنسول. Writel_ine("--------"); MemberInfo allMembers = t.GetMembersO; foreach (عضو MemberInfo در همه اعضا)

{

کنسول. WriteLine(member.ToStringO);

} > }

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

اطلاعاتی درباره کلاس اپلروش های اپل

Int32 GetHashCodeQ

System.String ToStringQ

RipenO را باطل کنید

System.Type GetTypeO

همه اعضای اپل

Int32 nSeeds

Int32 GetHashCodeO

معادلهای بولی (System.Object)

System.StringToStringO

RipenO را باطل کنید

System.Type GetTypeO

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

IIیک شی System.Type بر اساس تعریف کلاس دریافت کنید. Typet1 = typeof(Apple);

// شی System.Type را از شی دریافت کنید. سیب سیب= AppleQ جدید؛ نوع t2 = apple.GetTypeO;

اندازه

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

با استفاده از سیستم؛

کلاس BasicTypes(

// توجه: کد با استفاده از عملگر sizeof // باید به عنوان ناامن، استاتیک ناامن عمومی خالی علامت گذاری شود ShowSizesQ (

Console.WriteLine("\nانواع پایه Pa3Mephi"); Console.WriteLine("Pa3Mep short = (0)", sizeof(short)); Console.WriteLine("Pa3Mep int = (0)", sizeof(int)); Console.Writel_ine("Pa3Mep long = (0)", sizeof(long)); Console.WriteLine("Pa3Mep bool = (0)", sizeof(bool)); ))

کلاس UnsafeUpp

{

ناامن عمومی استاتیک void Main()

{

BasicTypes.ShowSizes();

} }

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

سایز انواع پایه سایز کوتاه = 2 سایز int = 4 سایز بلند = 8 سایز bool = 1

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

// با استفاده از عملگر sizeof. با استفاده از سیستم؛

ساختار StructWithNoMembers

ساخت StructWithMembers

{

شلوار کوتاه؛

int i;

طولانی1;

bool b; )

ساختار CompositeStruct

{

StructWithNoMembers a; StructWithMembersb;

StructWithNoMembers c; )

classUnSafe2App(

ناامن عمومی استاتیک void Main() ( Console.WriteLine("\nPa3Mep StructWithNoMembers ساختار = (0)"،

sizeof(StructWithNoMembers)); Console.WriteLine("\nPa3Mep StructWithMembers ساختار = (0)",

sizeof(StructWithMembers)); Console.WriteLine("\nPa3Mep CompositeStruct structure = (0)",

sizeof(CompositeStruct)); ))

اگر چه می توان فرض کرد که این برنامه برای یک ساختار بدون عضو 0 خروجی می دهد (StructWithNoMembers) 15 برای سازه ای با چهار عضو از نوع پایه (StructWithMembers)و 15 برای ساختاری که دو ساختار قبلی را جمع می کند (ساختار مرکب)در واقع نتیجه به این صورت خواهد بود:

اندازه ساختار StructWithNoMembers = 1 اندازه ساختار StructWithMembers = 16

اندازه ساختار CompositeStruct = 24

توضیح این مورد نحوه ذخیره سازه است ساختتوسط کامپایلر در فایل خروجی، که در آن کامپایلر توجیه و padding را اعمال می کند. به عنوان مثال، اگر ساختار 3 بایت باشد و تراز 4 بایت تنظیم شده باشد، کامپایلر به طور خودکار 1 بایت به ساختار و عبارت اضافه می کند. اندازهنشان می دهد که اندازه ساختار 4 بایت است. این را هنگام اندازه گیری ساختارها در سی شارپ در نظر داشته باشید.

بررسی شدو بدون علامت

این دو عملگر هنگام انجام عملیات ریاضی، بررسی سرریز را کنترل می کنند.

عملگرهای ریاضی

سی شارپ، مانند بسیاری از زبان های دیگر، از عملگرهای ریاضی پایه پشتیبانی می کند: ضرب (*)، تقسیم (/)، جمع (+)، تفریق (-) و مدول (%). هدف چهار عملگر اول از نام آنها مشخص است. عملگر مدول باقیمانده یک تقسیم عدد صحیح را تشکیل می دهد. در اینجا کدی وجود دارد که استفاده از عملگرهای ریاضی را نشان می دهد:

با استفاده از سیستم؛

کلاس MathOpsApp

{

public static void Main()

{

// کلاس System.Random بخشی از کتابخانه کلاس // .NET Framework است. متد Next در سازنده پیش‌فرض خود // از تاریخ/زمان فعلی به عنوان // استفاده می‌کند. مقدار اولیه. رند تصادفی = RandomO جدید; int a, b, c;

a = rand.Next() % 100; // مقدار محدود 99. b = rand.NextO % 100; // مقدار محدود 99.

Console.WriteLine("a=(0) b=(1)", a, b);

c = a * b;

Console.WriteLineC"a * b = (0)"، c);

// توجه داشته باشید که در اینجا از اعداد صحیح استفاده می شود. // بنابراین، اگر a کمتر از b باشد، نتیجه // همیشه 0 خواهد بود. برای به دست آوردن نتیجه دقیق تر، باید از // استفاده کنید. متغیرها را تایپ کنیددو یا شناور، c = a / b; Console.WriteLineC"a / b = (0)"، c);

Console.WriteLineC"a + b = (0)"، c);

Console.WriteLineC"a - b = (0)"، c);

Console.WriteLineC"a X b = (0)"، c); > >

عملگرهای Unary

دو عملگر واحد وجود دارد: مثبت و منفی. عملگر unary minus به کامپایلر می گوید که عدد منفی است. بنابراین در کد زیر آبرابر با -42 خواهد بود:

با استفاده از سیستم؛ با استفاده از سیستم؛

کلاس UnarylApp(

public static void Main()

{

int a = 0;

a = -42;

Console.WriteLine("(0)"، a); ))

با این حال، این کد یک ابهام ایجاد می کند: با استفاده از System;

کلاس Unary2App<

public static void Main() (

int a; int b = 2; int c = 42;

a = b * -c;

Console.WriteLine("(0)"، a); > >

اصطلاح آ= قبل از میلاد مسیحکاملا مشخص نیست باز هم استفاده از پرانتز این عبارت را روشن می کند:

// هنگام استفاده از پرانتز، واضح است که ما // b را در عدد منفی c ضرب می کنیم. a \u003d b * (-c)؛

اگر منهای unary برمی گردد معنی منفیعملوند، ممکن است فکر کنید که یک به علاوه یکنواخت مثبت است. با این حال، unary plus فقط عملوند را به شکل اصلی خود برمی گرداند و هیچ کار دیگری انجام نمی دهد، یعنی بر عملوند تأثیر نمی گذارد. به عنوان مثال، با اجرای این کد مقدار -84 را به دست می دهد:

با استفاده از سیستم؛

classUnarySapp(

public static void MainQ(

a = b * (+c)؛

Console.WriteLine("(0)"، a); ))

برای بدست آوردن مقدار مثبت، از تابع استفاده کنید ریاضی.این کد مقدار 84 را به دست می دهد:

با استفاده از سیستم؛

کلاس Unary4App

{

public static void Main()

int a; int b = 2; int c = -42;

a = b * Math.Abs(c); Console.Writel_ine("(0)", a); ))

آخرین عملگر یوناری که به آن اشاره کردم T(x) است. این یک نوع عملگر پرانتز است که به شما امکان می دهد یک نوع را به نوع دیگر منتقل کنید. از آنجا که با ایجاد یک تبدیل سفارشی می توان آن را بارگذاری کرد، در فصل 13 به آن خواهیم پرداخت.

بیانیه های انتساب مرکب

عملگر انتساب مرکب -این ترکیبی از عملگر باینری و عملگر انتساب (=) است. نحو این عملگرها به صورت زیر است:

کر = y

جایی که op -این یک اپراتور است. توجه داشته باشید که در این مورد، مقدار سمت چپ (lvalue)با راست جایگزین نمی شود (rvalue)عملگر مرکب همان اثر را دارد:

x = x opدر

و ارزشبه عنوان مبنایی برای نتیجه عملیات استفاده می شود.

توجه کنید که گفتم "همان اثر را دارد." کامپایلر عبارتی مانند آن را ترجمه نمی کند x += 5 اینچ ایکس= x + 5،او منطقی عمل می کند از جانب توجه ویژهچه زمانی باید در نظر گرفته شود ارزشیک روش است. کد را در نظر بگیرید:

با استفاده از سیستم؛

کلاس CompoundAssignmentlApp(

عناصر lnt محافظت شده؛

عمومی GetArrayElementO

{

عناصر بازگشتی؛

}

CompoundAssignment1App() (

عناصر = int جدید;

عناصر = 42;

}

public static void Main() (

برنامه CompoundAssignmentlApp = جدید CompoundAsslgnment1App();

Console.WrlteLine("(0>", app.GetArrayElement());

app.GetArrayElement() = app.GetArrayElement() + 5; Console.WriteLine("(0)"، app.GetArrayElement()); ). )

به خط برجسته شده توجه کنید - فراخوانی روش Compound-AssignmentlApp.GetArrayElementو سپس عنصر اول را تغییر دادم - در اینجا از نحو استفاده کردم:

x = x opدر

این کد MSIL است که تولید خواهد شد: // تکنیک ناکارآمد: x = x o y.

روش public hldebyslg static void Main() 11 مدیریت شد

Entrypolnt

// اندازه کد 79 (Ox4f) .maxstack 4

Locals (کلاس CompoundAssignmentlApp V_0)

IL_0000: نمونه newobj void CompoundAssignmentlApp::.ctor() IL_0005: stloc.O IL_0006: Idstr "(OG IL_OOOb: ldloc.0 ILJJOOc: نمونه تماس int32

CompoundAssignmentlApp::GetArrayElementO

IL_0011: ldc.14.0

IL_0012: Idelema["mscorlib"]System.Int32

IL_0017: جعبه [ 1 mscorlib"]System.Int32

IL_001c: فراخوانی void ["mscorlib 1 ]System.Console::WriteLine (کلاس System.String، کلاس System.Object)

IL_0021: ldloc.0

IL_0022: نمونه تماس int32 CompoundAssignmentlApp::GetArrayElementO

IL_0027: Idc.i4.0

IL_0028: ldloc.0

IL_0029: نمونه تماس int32 CompoundAssignmentlApp: :GetArrayElementO

IL_002e: Idc.i4.0

IL_002f: ldelem.14

IL_0030: ldc.14.5

IL_0031: اضافه کنید

IL_0032: فولاد.14

IL_0033: Idstr "(0)"

IL_0038: ldloc.0

IL_0039: تماس بگیرید

نمونه int32 CompoundAssignmentlApp::GetArrayElement() IL_003e: ldc.14.0

IL_003f: Idelema ["mscorlib"]Systera.Int32 IL_0044: جعبه ["msoorlib"]System.Int32 IL_0049: call void ["mscorlib"]System.Console::WriteLine

(کلاس System.String، کلاس System.Object) IL_004e: ret

) // پایان روش "CompoundAssignmentlApp::Main"!

به خطوط برجسته نگاه کنید: روش CompoundAssignmentlApp.Get-ArrayElementدر واقع دو بار نامیده می شود! این حداقل ناکارآمد و احتمالاً مضر است، بسته به اینکه روش چه کار دیگری انجام می دهد.

حالا بیایید به کد دیگری نگاه کنیم که از نحو انتساب ترکیبی استفاده می کند:

با استفاده از سیستم؛

کلاس CompoundAssignment2App(

عناصر int محافظت شده؛

عمومی GetArrayElementO

عناصر بازگشتی؛

}

CompoundAssignment2App() (

عناصر = int جدید;

عناصر = 42;

}

public static void Main() (

برنامه CompoundAssignment2App = جدید CompoundAssignment2App();

Console.WriteLine("(0)"، app.GetArrayElement());

app.GetArrayElement() += 5; Console.WriteLine("(0)"، app.GetArrayElement()); ))

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

// تکنیک کارآمدتر: xop = y.

روش عمومی hidebysig استاتیک void Main() یا مدیریت شده است

\ {

\.نقطه ورود

I // اندازه کد 76 (Ox4c) \ .maxstack 4

افراد محلی (کلاس CompoundAssignmentlApp V_0، int32 V_1) \ IL_0000: نمونه newobj void CompoundAssignmentlApp::.ctor() \ IL_0005: stloc.O 1 IL_0006: Idstr "(0)" 1 IL_OOOb: ldloc.0 IL_OOOc: نمونه تماس int32

CompoundAssignmentlApp::GetArrayElementO IL_0011: Idc.i4.0

IL_0012: Idelema [ mscorlib"]System.Int32 IL_0017: box [> mscorlib - ]System.Int32 lL_001c: call void ["mscorlib"]System.Console::WriteLine

(کلاس System.String، کلاس System.Object) IL_0021: ldloc.0 IL_0022: نمونه تماس int32

CompoundAssignmentlApp::GetArrayElement()

IL_0027: dup

IL_0028: stloc.1

IL_0029: Idc.i4.0

IL_002a: ldloc.1

IL_002b: Idc.i4.0

IL_002c: ldelem.14

IL_002d: ldc.14.5

IL_002e: اضافه کنید

IL_002f: فولاد.14

IL_0030: Idstr "(0)"

IL_0035: ldloc.0

IL_0036: نمونه تماس int32

CompoundAssignmentlApp::GetArrayElementO IL_003b:Idc.i4.0

IL_003c: Idelema["mscorlib"]System.Int32

IL_0041: box[mscorlib"]System.Int32

IL_0046: call void ["mscorlib"]System.Console::WriteLine

(کلاس System.String، کلاس System.Object)

IL_004b: ret ) // پایان روش "CompoundAssignmentlApp::Main"

می بینید که از دستور MSIL استفاده شده است. فریب دادنعنصر بالای پشته را کپی می کند، بنابراین یک کپی از مقدار بازگشتی توسط متد ایجاد می کند CompoundAssignmentlApp.Get Array Element. من

از اینجا می توان دریافت که اگرچه x +=yمعادل با x = x + y،کد MSIL در هر دو مورد متفاوت است. این تفاوت باید باعث شود که شما تعجب کنید که در هر مورد از کدام نحو استفاده کنید. یک قانون سرانگشتی و توصیه من این است که از عملگرهای انتساب ترکیبی در هر زمان و هر کجا که ممکن است استفاده کنید.

عملگرهای افزایش و کاهش

در C معرفی شد و به C++ و پورت شد اپراتورهای جاوا inc 1 -rement و decrement به شما این امکان را می دهند که به طور خلاصه بیان کنید که می خواهید یک مقدار عددی را با 1 افزایش یا کاهش دهید. یعنی /++ معادل افزودن 1 به مقدار فعلی / است.

وجود دو شکل عملگر افزایش و کاهش گاهی گیج کننده است. پیشوندو پسوندانواع این عملگرها در لحظه تغییر مقدار متفاوت است. در نسخه پیشوند عملگرهای افزایش و کاهش (++ ai - aبه ترتیب) ابتدا عملیات انجام می شود و سپس مقدار ایجاد می شود. در نسخه postfix (a++و آ-)ابتدا مقدار ایجاد می شود و سپس عملیات انجام می شود. به یک مثال توجه کنید:

با استفاده از سیستم؛

کلاس IncDecApp(

فضای خالی استاتیک عمومی Foo(int j)

{

Console.WriteLine("IncDecApp.Foo j = (0)"، j);

>

public static void Main() (

int i = 1;

Console.WriteLineC"flo به Foo(i++) = (0)"، i) فرا می خواند.

Console.WriteLine("پس از فراخوانی Foo(i++) = (0)", i);

Console.WriteLine("\n");

\ Console.WriteLineC"flo به Foo(++i) = (0)"، i);

\foo(++l);

\ Console.WrlteLine("پس از فراخوانی Foo(++i) = (0)", i);

l نتیجه اجرا به شرح زیر خواهد بود:

قبل از تماس با Foo(i++) = 1

IncDecApp.Foo j = 1

پس از فراخوانی Foo(i++) = 2

قبل از فراخوانی Foo(-n-i) = 2

IncDecApp.Foo j = 3

پس از فراخوانی Foo(++i) = 3

تفاوت این است چه زمانیمقدار ایجاد می شود و عملوند اصلاح می شود. وقتی تماس گرفته شود foo (i++)مقدار /" به متد ارسال می شود (بدون تغییر). فوو بعد ازبازگشت از روش / با 1 افزایش می یابد. به کد MSIL زیر نگاه کنید: دستور اضافه کردنپس از فشار دادن مقدار بر روی پشته اجرا می شود.

IL.0013: ldloc.0

IL.0014: dup

IL_0015: Idc.i4.1

IL_0016: اضافه کنید

IL_0017: stloc.O

IL_0018: call void IncDecApp::Foo(int32)

حال به فرم پیشوند اپراتور استفاده شده در تماس نگاه کنید فو (++a).در این صورت کد MSIL متفاوت خواهد بود. در عین حال تیم اضافه کردنانجام قبل ازچگونه مقدار برای فراخوانی متد بعدی به پشته فشار داده می شود فو

IL.0049: ldloc.0

IL_004a: Idc.i4.1

IL_004b: اضافه کنید

IL_004c: dup

IL_004d: stloc.O

IL_004e: call void IncDecApp::Foo(int32)

اپراتورهای رابطه ای

اکثر عملگرها مقادیر عددی را برمی گردانند. در مورد عملگرهای رابطه ای، آنها یک نتیجه بولی تولید می کنند. به جای / انجام عملیات ریاضی روی مجموعه ای از عملوندها، / عملگرهای رابطه ای رابطه بین عملوندها و برگشتمعنی درست است، واقعی،اگر نسبت درست باشد، نادرست-اگر/ نادرست است

اپراتورهای مقایسه

به عملگرهای رابطه ای فراخوانی شده است عملگرهای مقایسه،ارجاع)-sya "کمتر" (<), «меньше или равно» (<=), «больше» (>)، بزرگتر یا مساوی (>=)، مساوی با (==)، و نه مساوی با (!=). کاربرد این عملگرها برای اعداد واضح است، اما زمانی که با اشیاء استفاده می شود، اجرای آنها چندان واضح نیست. به عنوان مثال:

با استفاده از سیستم؛

کلاس NumericTest(

Public NumericTest (int 1)

{

this.i = i;

>

محافظت شده int 1; )

کلاس RelationalOpslApp(

public static void Main() (

NumericTest testl = جدید NumericTest(42); NumericTest test2 = NumericTest جدید (42);

Console.WriteLine("(0)", testl == test2); > )

اگر یک برنامه نویس جاوا هستید، می دانید که در اینجا چه اتفاقی قرار است بیفتد. با این حال، برنامه نویسان ++C احتمالاً از دیدن نتیجه شگفت زده خواهند شد نادرستاجازه دهید یادآوری کنم: با ایجاد یک نمونه از یک شی، به آن اشاره می کنید. این بدان معنی است که هنگام مواجهه با یک عملگر رابطه ای که دو شی را با هم مقایسه می کند، کامپایلر C# نه محتویات اشیاء، بلکه آدرس های آنها را مقایسه می کند. برای درک بهتر این موضوع، کد MSIL را در نظر بگیرید:

\ .method public hldebysig static void MainQ یا مدیریت شده

\ .نقطه ورود

\ // اندازه کد 39 (0x27)

1.maxstack 3

افراد محلی (کلاس NumericTest V_0، \ کلاس NumericTest V_1، 1 bool V_2)

ILJOOO: Idc.i4.s 42

1L_0002: نمونه newobj void NumericTest::.ctor(int32)

IL_0007: stloc.O

IL_0008: Idc.i4.s 42

IL_OOOa: نمونه newobj void NumericTest::.ctor(int32)

IL_OOOf: stloc.1

IL_0010: Idstr "(0)"

IL_0015: ldloc.0

IL_0016: ldloc.1

IL_0017: eeq

IL_0019: stloc.2

IL_001a: Idloca.s V_2

IL_001c: جعبه["mscorlib"]System.Boolean

IL_0021: call void ["mscorlib"]System.Console::WriteLine

(کلاس System.String، کلاس System.Object)

IL_0026: ret ) // پایان روش "RelationalOpslApp::Main"

به خط نگاه کن محلی ها.کامپایلر مشخص می کند که متد اصلیسه متغیر محلی دو مورد اول اشیا هستند تست عددی،یک سوم یک متغیر بولی است. حالا بریم سراغ خطوط IL_0002و IL_0007.اینجا جایی است که یک شیء نمونه سازی می شود تستل،و با آن پیوند دهید stlocدر اولین متغیر محلی ذخیره می شود. مهم است که MSIL آدرس شی جدید ایجاد شده را ذخیره کند. سپس در خطوط IL_OOOaو IL_OOO ازکدهای MSIL را برای ایجاد شی می بینید تست 2و ذخیره مرجع برگشتی در یک متغیر محلی دوم. در نهایت، در خطوط 1LJ-015و IL_0016متغیرهای محلی توسط دستور به پشته فشار داده می شوند IDloc،و در صف IL_0017تیم خاکستریدو مقدار را در بالای پشته مقایسه می کند (یعنی ارجاعات شی testlو testl).مقدار بازگشتی در یک متغیر محلی سوم ذخیره می شود و سپس توسط متد خروجی می شود سیستم.کنسول. خط نوشتن

اما چگونه می توان اعضای دو شی را با هم مقایسه کرد؟ پاسخ این است که از کلاس پایه ضمنی تمام اشیاء .NET Framework استفاده کنید. یعنی برای این اهداف کلاس System.Objectیک روش وجود دارد برابر است.به عنوان مثال، کد زیر / محتویات اشیاء و خروجی ها را با هم مقایسه می کند، همانطور که / انتظار دارید، درست: من

با استفاده از سیستم؛ /

کلاس RelationalOps2App

(/ public static void Main() (

Console.WriteLine("(0)", testl.Equals(test2));

مثال RelationalOpslApp از یک کلاس "self-made" استفاده می کند (Nu-mericTest) ودر مثال دوم - کلاس دات نت (اعشاری).نکته این است که روش System.Object.Equalsبرای انجام مقایسه واقعی اعضا باید لغو شود. بنابراین، روش برابر استبا کلاس تست عددیکار نخواهد کرد زیرا ما روش را لغو نکرده ایم. و اینجا کلاس است اعشاریروشی را که به ارث می برد نادیده می گیرد برابر است،و در این صورت همه چیز کار خواهد کرد.

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

اپراتورهای واگذاری ساده

مقدار سمت چپ یک دستور انتساب فراخوانی می شود ارزش،و در سمت راست - rvalueمانند rvalueمی تواند هر ثابت، متغیر، عدد یا عبارتی باشد که نتیجه آن با آن سازگار باشد ارزشدر همین حال ارزشباید متغیری از نوع خاصی باشد. نکته این است که مقدار از سمت راست به سمت چپ کپی می شود. بنابراین، یک فضای آدرس فیزیکی باید برای مقدار جدید اختصاص داده شود. به عنوان مثال، می توانید /" = را بنویسید 4, زیرا / بسته به نوع / در حافظه - روی پشته یا پشته - جایی دارد. و اپراتور اینجاست 4 = 1 نمی توان اجرا کرد زیرا 4 یک مقدار است، نه متغیری که محتویات آن در حافظه قابل تغییر است. به هر حال، من توجه می کنم که در C # به عنوان ارزشمی تواند یک متغیر، یک ویژگی یا یک نمایه ساز باشد. برای اطلاعات بیشتر در مورد خصوصیات و نمایه سازها به فصل 7 مراجعه کنید.در این فصل از متغیرها برای سادگی استفاده می کنم. اگر با تکلیف مقادیر عددیهمه چیز به اندازه کافی روشن است، با اشیا موضوع پیچیده تر است. اجازه دهید به شما یادآوری کنم که وقتی با اشیا سروکار دارید، عناصر پشته را دستکاری نمی کنید، که به راحتی کپی و جابجا می شوند. در مورد اشیا، شما واقعاً فقط به برخی از موجودیت‌هایی اشاره دارید که به صورت پویا حافظه تخصیص داده می‌شوند. بنابراین، هنگامی که می‌خواهید یک شی (یا هر نوع مرجع) را به یک متغیر اختصاص دهید، این داده‌ها نیستند که در مورد انواع مقادیر کپی می‌شوند، بلکه ارجاعات هستند.

فرض کنید دو شی دارید: testlو تست 2.اگر مشخص کنید testl= test2، testlکپی نخواهد بود تست 2.مطابقت خواهند داشت! یک شی testlبه همان حافظه اشاره می کند تست 2،و هر گونه تغییر در جسم testlمنجر به تغییر شود تست 2.در اینجا برنامه ای وجود دارد که این را نشان می دهد:

با استفاده از سیستم؛

کلاس Foo(

عمومی int i; )

کلاس RefTestlApp(

پویایی استاتیک عمومی MainO(

Foo testl = new Foo(); testl.i = 1;

Foo test2 = new Foo(); test2.i = 2;

Console.WriteLine("قبل از تخصیص اشیا"); Console.WriteLine("test1.i=(0>", testl.i); Console.WriteLine("test2.i=(0)"، test2.i); Console.WriteLine("\n");

testl = test2;

Console.Writel_ine("پس از انتساب اشیا");

Console.WriteLine("test1.i=(0)", testl.i); Console.WriteLine("test2.i=(0)", test2.i); Console.WriteLine("\n");

testl.i = 42; ;"

Console.WriteLine("پس از تغییر فقط عضو TEST1"); Console.WriteLine("test1.i=(0)", testl.i); Console.WriteLine("test2.i=(0)", test2.i); Console.WriteLine("\n"); ))

وقتی این کد را اجرا می کنید، خواهید دید:

قبل از تخصیص شی

test1.i=1

test2.i=2

پس از اختصاص یک شی

testt.i=2

test2.i=2

پس از تغییر فقط عضو TEST1

test1.i=42

test2.i=42

بیایید ببینیم در هر مرحله از اجرای این مثال چه اتفاقی می افتد. فو-این یک کلاس k ساده با یک عضو، / است. دو نمونه از این کلاس در متد Main ایجاد می شود: testlو تست 2- و اعضای آنها منبه ترتیب روی 1 و 2 تنظیم می شوند. سپس این مقادیر خروجی می شوند و همانطور که انتظار می رود، testl.iبرابر با 1، a test2.i- 2. و اینجا سرگرمی شروع می شود! AT خط بعدیهدف - شی testlاختصاص داده تست 2.خوانندگان برنامه نویسی جاوا می دانند که چه چیزی در آینده رخ می دهد. با این حال، اکثر برنامه نویسان C++ انتظار عضو/شیء را دارند testlاکنون برابر با یک عضو شی است تست 2(با فرض اینکه هنگام کامپایل چنین برنامه ای، نوعی عملگر کپی عضو شی اجرا شود). به نظر می رسد نتیجه خروجی این را تایید می کند. با این حال، در واقع، ارتباط بین اشیاء در حال حاضر بسیار عمیق تر است. بیایید مقدار 42 را به عبارت اختصاص دهیم testl.iو دوباره نتیجه را در خروجی قرار دهید. و؟! هنگام تغییر یک شی testlتغییر کرد و testZاین اتفاق افتاد زیرا شی testlبیشتر نه. پس از تعیین تکلیف او تست 2یک شی testlاز بین می رود زیرا برنامه دیگر به آن ارجاع نمی دهد و در نتیجه توسط جمع کننده زباله (زباله جمع آوری، GC) "پاکسازی" می شود. اکنون testlو تست 2به همان حافظه روی پشته اشاره کنید. بنابراین، هنگامی که یک متغیر تغییر می کند، کاربر تغییری را در متغیر دیگر مشاهده می کند.

به دو خط خروجی آخر توجه کنید: اگرچه فقط مقدار در کد تغییر کرده است testl.i،معنی test2.iنیز تغییر کرد. بار دیگر، هر دو متغیر اکنون به یک مکان حافظه اشاره می کنند، که رفتاری است که برنامه نویسان جاوا انتظار دارند. با این حال، این به هیچ وجه انتظارات توسعه دهندگان C ++ را برآورده نمی کند، زیرا در این زبان کپی کردن اشیاء انجام می شود: هر متغیر دارای کپی منحصر به فرد خود از اعضا است و تغییرات یک شی بر روی شی دیگر تأثیر نمی گذارد. از آنجایی که این کلید درک نحوه کار اشیا در سی شارپ است، بیایید یک قدم به عقب برگردیم و ببینیم وقتی یک شی را به یک متد ارسال می کنیم چه اتفاقی می افتد:

با استفاده از سیستم؛

کلاس Foo(

عمومی int i; )

کلاس RefTest2App(

Public void ChangeValue (Foo f)

{

f.i = 42;

}

public static void Main() (

برنامه RefTest2App = RefTest2App جدید ();

Foo test = new Foo(); test.i = 6;

Console.WriteLine("قبل از فراخوانی متد"); Console.WriteLine("test.i=(0)", test.i); Console.WriteLine("\n");

app.ChangeValue(test);

Console.WriteLine("پس از فراخوانی روش"); Console.WriteLine("test.i=(0)", test.i); Console.WriteLine("\n"); > )

در اکثر زبان ها به جز جاوا، این کد شی ایجاد شده را کپی می کند تست درروش پشته محلی RefTest2App.ChangeValue.در این مورد، شی تست،ایجاد شده در روش اصلی،هرگز تغییراتی را در شیء ایجاد شده در متد مشاهده نخواهد کرد ChangeValue.با این حال، من تکرار می کنم که روش اصلییک ارجاع به یک شیء تخصیص داده شده توسط پشته ارسال می کند تست.زمانی که روش ChangeValueمتغیر محلی خود را دستکاری می کند // همچنین مستقیماً شی را دستکاری می کند تستروش اصلی

جمع بندی

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

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