سی شارپ؛ تعریف و بررسی 10 اشتباه رایج برنامه نویسی سی شارپ
سی شارپ، زبانی چند پلتفرمی است؛ به این معنی که میتوان از آن برای توسعه برنامههایی برای سیستم عاملهای مختلف مانند ویندوز (اعم از ویندوز 10 اینترپرایز)، لینوکس و macOS استفاده کرد. در واقع، سی شارپ یک زبان قدرتمند و انعطاف پذیر با مکانیسمها و پارادایمهای بسیاری است که میتواند بهرهوری را تا حد زیادی بهبود بخشد. قبل از اینکه به سراغ سی شارپ و اشتباهات رایج آن هنگام برنامه نویسی برویم، بهتر است با تنظیم رزولوشن مانیتور در ویندوز 10، با کیفیت مورد نظر خود به سراغ آنها برویم.
این مقاله 10 مورد از رایج ترین اشتباهات برنامه نویسی را که برنامه نویسان سی شارپ مرتکب می شوند یا تلههایی که باید از آنها اجتناب کرد، شرح داده می شود.
درباره سی شارپ
سی شارپ یک زبان شی گرای strongly-typed است. بررسی دقیق نوع (type) در سی شارپ، هم در زمان کامپایل و هم در زمان اجرا، منجر به این می شود که اکثر خطاهای معمول برنامه نویسی سی شارپ در اسرع وقت گزارش شوند و مکان های آنها کاملاً دقیق مشخص شود.
اشتباهات رایج برنامه نویسی سی شارپ چیست؟
این آموزش 10 مورد از رایج ترین اشتباهات برنامه نویسی سی شارپ را که برنامه نویسان سی شارپ مرتکب شده اند یا مشکلاتی که باید از آنها اجتناب شود را شرح می دهد.
اشتباه رایج برنامه نویسی سی شارپ شماره 1: استفاده از مرجعی مانند یک مقدار یا بالعکس
برنامه نویسان ++C و بسیاری از زبان های دیگر عادت دارند که کنترل کنند مقادیری که به متغیرها نسبت می دهند صرفاً مقادیر هستند یا ارجاع به اشیاء موجود هستند. با این حال، در برنامه نویسی سی شارپ، این تصمیم توسط برنامه نویسی گرفته می شود که شی را نوشته است، نه برنامه نویسی که شی را نمونه سازی می کند و آن را به یک متغیر اختصاص می دهد. این یک “گوچا” رایج برای کسانی است که سعی در یادگیری برنامه نویسی #C دارند.
همانطور که می بینید، هر دو شی Point و Pen دقیقاً به یک شکل ایجاد شده اند، اما مقدار point1 بدون تغییر باقی ماند زمانی که یک مقدار مختصات جدید X به point2 اختصاص داده شد، در حالی که مقدار pen1 زمانی که یک رنگ جدید به pen2 اختصاص داده شد تغییر کرد. بنابراین می توانیم نتیجه بگیریم که point1 و point2 هر کدام دارای کپی مخصوص به خود از یک شی Point هستند، در حالی که pen1 و pen2 حاوی ارجاعاتی (references) به همان شی Pen هستند. اما چگونه می توانیم بدون انجام این آزمایش آن را بدانیم؟
پاسخ این است که به تعاریف انواع شی نگاه کنید (که می توانید به راحتی در ویژوال استودیو با قرار دادن مکان نما روی نام نوع شی و فشار دادن F12 انجام دهید).
اشتباه رایج برنامه نویسی سی شارپ شماره 2: درک اشتباه مقادیر پیش فرض برای متغیرهای بدون مقدار اولیه
در سی شارپ، انواع مقادیر نمی توانند null باشند. طبق تعریف، انواع مقادیر دارای یک مقدار هستند و حتی متغیرهای بدون مقدار اولیه انواع مقدار باید دارای یک مقدار باشند. این همان مقدار پیش فرض برای آن نوع نامیده می شود. این منجر به نتایج زیر (و معمولاً غیرمنتظره) هنگام بررسی اینکه آیا یک متغیر مقداردهی نشده است می شود.
چرا point1 برابر با null نیست؟ پاسخ این است که Point یک نوع مقدار است و مقدار پیش فرض یک Point برابر با (0,0) است، نه null . عدم تشخیص این یک اشتباه بسیار آسان (و رایج) در سی شارپ است.
هنگامی که بررسی می کنید که آیا متغیری مقداردهی اولیه شده است یا خیر، مطمئن شوید که می دانید یک متغیر بدون مقدار اولیه از آن نوع به طور پیش فرض چه مقداری خواهد داشت و به تهی بودن (null) آن متکی نباشید.
اشتباه رایج برنامه نویسی سی شارپ شماره 3: استفاده از متد های مقایسه رشته نامشخص یا نامناسب
روش های مختلفی برای مقایسه رشته ها در سی شارپ وجود دارد. اگرچه بسیاری از برنامه نویسان از عملگر == برای مقایسه رشته ها استفاده می کنند، اما در واقع یکی از نا مطلوب ترین متد ها برای استفاده است، در درجه اول به این دلیل که به صراحت در کد مشخص نمی کند که کدام نوع مقایسه مورد نظر است.
اشتباه رایج برنامه نویسی سی شارپ شماره 4: استفاده از عبارات تکراری (به جای اعلانی) برای دستکاری مجموعه ها
برخی از برنامه نویسان سی شارپ حتی از وجود LINQ اطلاعی ندارند، اما خوشبختانه این تعداد به طور فزاینده ای در حال کوچک شدن اشت. با این حال، بسیاری هنوز فکر می کنند که به دلیل شباهت بین کلمات کلیدی LINQ و عبارات SQL ، تنها کاربرد آن در کدهایی است که پایگاه های داده را کویری می کنند.
در حالی که این یک مثال بسیار ساده برای جلوگیری از این مشکل رایج برنامه نویسی #C است، مواردی وجود دارد که یک دستور LINQ می تواند به راحتی جایگزین ده ها دستور در یک حلقه تکراری (یا حلقه های تودرتو) شود. و کد کمتر به معنای فرصت کمتری برای ایجاد باگ است.
به خاطر داشته باشید، با این حال، ممکن است یک معاوضه از نظر عملکرد وجود داشته باشد. در سناریوهایی که در آنها کارایی و عملکرد حیاتی است، به خصوص در جایی که کد تکراری شما می تواند مفروضاتی را درباره مجموعه شما ایجاد کند که LINQ نمی تواند، مطمئن شوید که یک مقایسه عملکرد بین دو متد انجام دهید.
اشتباه رایج برنامه نویسی سی شارپ شماره 5: شکست در در نظر گرفتن اشیاء زیرین در یک دستور LINQ
LINQ برای انتزاعی کردن کار دستکاری مجموعه ها، چه اشیاء درون حافظه، جداول پایگاه داده یا اسناد XML عالی است. در یک دنیای ایده آل، عالی و کامل، نیازی نیست که بدانید اشیاء زیرین (underlying objects) چیست. اما خطای اینجا این است که فرض کنیم در یک دنیای کامل زندگی می کنیم. در واقع، دستورات LINQ یکسان می توانند نتایج متفاوتی را هنگام اجرا بر روی همان داده به دست آورند، اگر آن داده ها در قالب متفاوتی باشند.
اما یک دقیقه صبر کنید. وقتی قبلاً در مورد مقایسه رشته ها صحبت کردیم، دیدیم که عملگر == یک مقایسه ترتیبی از رشته ها را انجام می دهد. پس چرا در این مورد عملگر == مقایسه ای را انجام می دهد که حساس به حروف بزرگ و کوچک نیست؟
به طور کلی، اگرچه LINQ یک روش مفید و ثابت برای پرس و جوی مجموعه اشیاء است، در واقع شما هنوز باید بدانید که آیا عبارت شما به چیزی غیر از #C ترجمه می شود یا خیر تا مطمئن شوید که رفتار کد شما در زمان اجرا مطابق انتظار باشد.
اشتباه رایج برنامه نویسی سی شارپ شماره 6: گیج شدن یا جعلی شدن با متدهای توسعه
پس متد ()Sum کجا تعریف شده است؟ سی شارپ به شدت به نوشتن حساس است، بنابراین اگر ارجاع به متد Sum نامعتبر باشد، کامپایلر سی شارپ مطمئناً آن را به عنوان یک خطا علامت گذاری می کند. بنابراین ما می دانیم که باید وجود داشته باشد، اما کجا؟ علاوه بر این، تعاریف همه متد های دیگری که LINQ برای پرس و جو یا جمع آوری این مجموعه ها ارائه می کند کجاست؟
این واقعیت که ما می توانستیم آن را به این روش پیاده سازی کنیم، این سوال را ایجاد می کند که چرا اصلاً متدهای extension وجود دارند؟ extension methods اساساً راحتی زبان برنامه نویسی سی شارپ هستند که شما را قادر می سازد تا بدون ایجاد نوع مشتق شده جدید، کامپایل مجدد یا تغییر نوع اصلی، متدها را به انواع موجود اضافه کنید.
در حالی که مطمئناً استفاده از extension methods مزایایی دارد، اما می تواند مشکلاتی ایجاد کند و برای توسعه دهندگانی که از آن ها آگاه نیستند یا به درستی آن ها را درک نمی کنند، معضلی در کمک به برنامه نویسی سی شارپ شود. این امر به ویژه در هنگام مشاهده نمونه کدهای آنلاین یا هر کد از پیش نوشته شده دیگری صادق است.
وقتی چنین کدی خطاهای کامپایلر ایجاد می کند (زیرا متدهایی را فراخوانی می کند که به وضوح در کلاس هایی که فراخوانی شده اند تعریف نشده اند)، مایل هستیم که فکر کنیم این کد برای نسخه دیگری از کتابخانه یا کلاً برای کتابخانه دیگری اعمال می شود. زمان زیادی را می توان صرف جستجوی نسخه جدید یا فانتوم «کتابخانه گمشده» که وجود ندارد، صرف کرد.
اشتباه رایج برنامه نویسی سی شارپ شماره 7: استفاده از نوع نامناسب مجموعه برای تسک مورد نظر
سی شارپ طیف گسترده ای از مجموعه اشیاء را ارائه می دهد که موارد زیر فقط یک لیست جزئی است:
Array, ArrayList, BitArray, BitVector32, Dictionary<K,V>, HashTable, HybridDictionary, List, NameValueCollection, OrderedDictionary, Queue, Queue, SortedList, Stack, Stack, StringCollection, StringDictionary.
در حالی که ممکن است مواردی وجود داشته باشد که انتخاب های بسیار زیاد به همان اندازه بد باشد که انتخاب های کافی وجود ندارد، این مورد در مورد مجموعه اشیاء صدق نمی کند. تعداد گزینه های موجود قطعا می تواند به نفع شما باشد. کمی وقت اضافی را برای تحقیق و انتخاب نوع مجموعه بهینه برای هدف خود اختصاص دهید. این امر احتمالاً منجر به عملکرد بهتر و فضای کمتری برای خطا خواهد شد.
اگر نوع مجموعه ای وجود دارد که به طور خاص برای نوع عنصر شما (مانند رشته یا بیت) هدف قرار گرفته است، ابتدا به استفاده از آن متمایل شوید. پیاده سازی به طور کلی زمانی کارآمدتر است که نوع خاصی از عنصر را هدف قرار دهد.
اشتباه رایج برنامه نویسی سی شارپ شماره 8: بی توجهی به منابع رایگان
اگر در حال ایجاد و حذف یک شی در متن یک بلوک کد واحد هستید، اساساً فراموشی فراخوانی ()Dispose غیرقابل توجیه است، زیرا سی شارپ یک دستور استفاده را ارائه می دهد که اطمینان حاصل می کند که ()Dispose بدون توجه به اینکه بلوک کد چگونه خارج می شود فراخوانی می شود (خواه یک استثنا باشد، یک عبارت بازگشتی یا صرفاً بسته شدن بلوک).
بله، این همان عبارتی است که قبلا ذکر شد و برای گنجاندن فضاهای نام #C در بالای فایل شما استفاده می شود. این یک هدف دوم و کاملا نامرتبط دارد که بسیاری از توسعه دهندگان سی شارپ از آن بی اطلاع هستند، یعنی، برای اطمینان از اینکه هنگام خروج از بلوک کد، ()Dispose بر روی یک شیء فراخوانی می شود.
اشتباه رایج برنامه نویسی سی شارپ شماره 9: دوری از استثناها و خطاها
سی شارپ به اجرای ایمنی type خود در زمان اجرا ادامه می دهد. این به شما امکان می دهد تا بسیاری از انواع خطاها را در سی شارپ خیلی سریع تر از زبان هایی مانند ++C مشخص کنید، جایی که تبدیل type مشکلدار می تواند منجر به تخصیص مقادیر دلخواه به فیلدهای یک شی شود.
با این حال، یک بار دیگر، برنامه نویسان می توانند این ویژگی عالی را هدر دهند و منجر به مشکلات #C شود. آنها در این تله می افتند زیرا سی شارپ دو روش مختلف برای انجام کارها ارائه می دهد، یکی که می تواند استثنا ایجاد کند و دیگری که این کار را نمی کند. برخی از مسیر استثنا و خطا دوری می کنند و تصور می کنند که عدم نیاز به نوشتن بلوک try/catch باعث می شود که مقداری کدنویسی کمتر شود.
اشتباه رایج برنامه نویسی سی شارپ شماره 10: اجازه جمع آوری هشدارهای کامپایلر
در حالی که این مشکل قطعاً مختص سی شارپ نیست، به ویژه در برنامه نویسی سی شارپ فاحش است، زیرا مزایای بررسی دقیق نوع ارائه شده توسط کامپایلر C# را کنار گذاشته است.
یک مثال ساده رایج برای این آموزش برنامه نویسی سی شارپ زمانی است که الگوریتم خود را تغییر می دهید تا استفاده از متغیری را که استفاده می کردید حذف کنید، اما فراموش می کنید که تعریف متغیر را حذف کنید. برنامه به خوبی اجرا می شود، اما کامپایلر هشداری در مورد بی استفاده بودن تعریف متغیر می دهد.
این واقعیت که برنامه به طور کامل اجرا می شود باعث می شود برنامه نویسان از رفع علت هشدار غافل شوند. علاوه بر این، برنامه نویسان از آن ویژگی ویژوال استودیو استفاده می کنند که به راحتی می توانند اخطارها را در پنجره “لیست خطا” پنهان کنند تا بتوانند فقط بر روی خطاها تمرکز کنند. طولی نمی کشد تا ده ها هشدار وجود داشته باشد که همه آنها نادیده گرفته شده اند (یا حتی بدتر از آن، پنهان شده اند). و با سرعتی که Intellisense به ما اجازه می دهد کد بنویسیم، این خطا آنقدر که به نظر می رسد بعید نیست.