کار اصلی دستورات پیش پردازنده در هر زبانی فراهم کردن اطلاعاتی برای کامپایر در مورد بخش هایی از کد است. در سی شارپ ۱۰ دستور پیش پردازنده وجود دارد. که به آنها نگاهی می اندازیم.
#define symbol
این دستور برای تعریف کردن یک نماد (symbol) استفاده می شود. نماد ها معمولا برای کامپایل شرطی بخش هایی از کد استفاده می شوند. به طور مثل نماد معروف DEBUG به ما کمک می کند با استفاده از دستورات پیش پردازنده شرطی، بخش هایی از کد را فقط در حالت DEBUG یا عدم وجود DEBUG کامپایل کنیم.
#if condition – #endif condition
1 2 3 4 5 |
public void Log(string message){ #if DEBUG Console.WriteLine(message); #endif } |
اگر نماد DEBUG در هنگام کامپایل برنامه تعریف شده باشد خط مربوط به چاپ کردن پیغام روی کنسول، کامپایل خواهد شد. (دقت کنید که گفتم کامپایل نه اجرا در واقع اگر نماد DEBUG تعریف نشده باشد در dll حاصل از کامپایل اثری از این خط نخواهد بود)
نکته: مثال مربوط به لاگ زدن فقط برای انتقال مطلب نوشته شده است. قطعا راههای مناسبتر و اصولی تری برای این نوع لاگ زدن وجود دارد که توضیح آن در موضوع این مطلب نیست.
#else – #elseif condition
همان طور که عنوان خود دستورات نشان می دهند این دستورات حالت else مربوط به بررسی شرط را ایجاد خواهند کرد مثلا وقتی نیاز است بر اساس وجود یا عدم وجود نماد DEBUG کارهای متفاوتی انجام دهیم. #elseif هم همینطور.
نکته مهم: نمادها هم از طریق فایل های کد قابل تعریف هستند و هم می توان آنها را در هنگام کامپایل به کامپایلر پاس داد. با استفاده از این امکان ویژوال استودیو نماد DEBUG را (در هنگامی که پروفایل build مربوط به DEBUG را انتخاب می کنیم)، به پارامتر های قابل پاس داده شده به کامپایلر اضافه می کند. سویچ خط فرمانی مورد استفاده برای این کار به صورت زیر است.
1 |
/define:symbol |
نکته: علاوه بر این که می توان نماد ها را در فایل کد نیز تعریف کرد ویژوال استودیو رابط کاربری ای برای این کار ارائه می دهد که از همین نکته بالا برای عملی کردن آن استفاده می کند.
از مسیر زیر تب مربوط به properties یک پروژه را باز کنید:
Right click on project node in solution explorer / Properties (item)

اگر به تصویر بالا دقت کرده باشید متوجه می شوید در واقع هر پروفایل build ای مجموعه ای از properties را به هر پروژه اختصاص می دهد، که برای DEBUG تعریف نماد DEBUG را هم شامل می شود.
#undef symbol
نمادی را که به صورت پارامتر به آن داده می شود را از بین می برد.
#warning message
این دستور پیش پردازنده پیغام warning ای را در خروجی کامپایل کامپایلر نمایش خواهد داد.
1 2 3 4 5 6 7 |
public void Log(string message){ #if DEBUG Console.WriteLine(message); #else #warning Log will not work in a mode other than debug. #endif } |
در تکه کد بالا اگر نماد DEBUG تعریف شده باشد، کد به صورت عادی کامپایل می شود و کد مربوط به چاپ پیغام روی کنسول هم کامپایل خواهد شد. در صورتی که نماد DEBUG تعریف نشده باشد یک warning مبنی بر این که لاگ کار نخواهد کرد روی خروجی کامپایلر نمایش داده خواهد شد.
#error message
دقیقا مانند warning# قابل استفاده است با این تفاوت که خطایی در خروجی کامپایلر نمایش داده خواهد شد و برنامه به صورت موفق کامپایل نخواهد شد.
#region name – #endregion
نیاز به توضیح ندارد!
مورد استفاده: از این دستورات برای بخش بندی کد استفاده می کنند خیلی از IDE ها از این دستورات برای نمایش نود های متفاوت کد به صورت دسته بندی شده استفاده می کنند.
#pragma
برای غیر فعال کردن warning بوجود آمده برای بخشی از کد استفاده می شود.
1 2 3 4 5 6 7 8 9 |
public void Log(string message){ #if DEBUG Console.WriteLine(message); #else #pargma warning disable #warning Log will not work in a mode other than debug. #pragma warning restore #endif } |
در تکه کد بالا اگر حتی نماد DEBUG تعریف نشده باشد هم warning ای در خروجی کامپایلر نمایش داده نخواهد شد. به این خاطر که ما تمامی warning های حاصل از آن بخش کد را غیر فعال کردیم.
نکته مهم: اگر از امکان restore استفاده نکنیم برای آن بخشی از کد که بعد از disable هستند نیز تمامی warning ها غیر فعال خواهند شد.
مورد استفاده: از این دستور بیشتر در زمانی استفاده می شود که ما تغییری در کد داده ایم که منجر به ایجاد warning شده و میخو اهیم به کامپایلر بگوییم خودم حواسم هست! مثلا وقتی عمدا unreachable کد در کدهای ما ایجاد می شود و ما میخوام هیج warning ای نگیریم.
ConditionAttribute
این attribute در namespace این به آدرس System.Diagnostics قرار دارد.
از این attribute می توانیم برای کامپایل کردن متدی بر اساس شرطی از نماد ها استفاده کنیم. به طور مثال
1 2 3 4 |
[Condition(“DEBUG”)] public void Log(string message){ Console.WriteLine(message); } |
در مثال بالا ما به کامپایلر می گوییم که اگر نماد DEBUG وجود داشت متد را کامپایل کند. (البته این مثال خیلی معنا دار نیست چون باید به فکر زمانی هم باشیم که متد کامپایل نشده است و تمام استفاده های ما از این متد به خطا خواهند خورد)
دستورات پیش پردازنده مورد های استفاده عجیب و غریبی ندارند. شاید ماهها با این دستورات سر و کار نداشته باشیم. ولی خوشحال می شوم نمونه هایی از استفاده های خود را با من به اشتراک بگذارید.
خیلی خوب بود .
مرسی، پرکاربرد بود.