Dustin Metzgar - .NET in Action-Manning Publications (2024)

این کتاب فرض رو بر این گذاشته که یه دانشی از OOP داشته باشیم و توی این کتاب نمیاد C# رو به صورت تفصیلی توضیح بده فقط نکته های مهم شو میگه

https://github.com/dmetzgar/dotnet-in-action-code

خوب .net چیزی که نوشته اینه که open source هستش و یه runtime نه زبان برنامه نویسی خوب .net runtime فقط یه زبان رو میفهمه اونم cil هستش که مخفف common intermadiate language هستش ، خوب cil میشه گفت زبان low level هستش شبیه به assembly

خوب .net یه کامپایلر داره که زبون های سطح بالا رو به CIL تبدیل میکنه

خوب وقتی کد به صورت .net نوشته میشه کدش به پروژه های .net دیگه میتونه وصل بشه ، چون اصلا فرقی نمیکنه در آخر همه اون پروژه ها تبدیل میشن به CIL

خوب اینطوری که متوجه شدم اینطوری که به این زبون ها هم میشه برنامه نوشت و اون ها رو به Cil تبدیل میکنه

خوب runtime میشه یه مترجم که میاد کد رو به یه فرمت خاص میخونه مثل IL

به اون runtime میگن CoreCLR که CLR میشه common language runtime

و runtime یه سری قابلیت ها داره مثل JIT و memory managment

و .net یه سری class library داره که بهش میگن framework class library که ارجاع میدن به core fx که قدیمیا بهش میگن base class library

خیلی از function ها ، الگوریتم ها ، کنسول و … توی همون کتابخونه هستش

خوب .net یه webframework هستش که میتونی host بشه روی پلتفرم سرور kerstel یا روی IIS که میشه همون internet information service

خوب kerstel به .net این قابلیت رو میده که ,net روی container ها اجرا بشه که همین قضیه باعث میشه که بهترین آپشن باشه برای microservice ها

خوب blazor web assembly این قابلیت رو میده که روی مرورگر .net اجرا بشه که خوده blazor حالت hybrid داره که میتونه هم روی سرور و هم روی clinet اجرا بشه

روی سخت افزا ها هم اجرا میشه

برای این که آنلاین contribute کنیم گفته بریم

https://dotnetfoundation.org

خوب DOTVVM یه پروژه است که رفت امد کردن و درخواست ها رو به دیتابیس کم میکنه با استفاده از قابلیتی به اسم knockout js این کار رو میکنه و Open source هستش

خوب ANT design , oqtane پروژه های blzor هستد که جالبند

اینجا .net یه سری پروژه ها خوب داره که میتونیم استفاده کنیم ازشون

پروژه های open source

جاهایی که میشه یا بهتره از .net استفاده نشه

خوب راجع به این داستان ها صحبت میکنه

راجع به این basic ها صحبت میکنه

هر کدی که میزنیم باید تبدیل بشه به چیزی که ماشین بتونه بخونه حالا چیزی که ماشین بتونه بخونه یعنی این که processor بتونه اون رو اجرا کنه که همین نیاز داره که instruction درستی رو استفاده کنه که دو تا معماری معروف داریم x86 و Arm

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

وقتی که کدمون به Cil تبدیل بشه بعنی این که binry برنامه مون ( یعنی همون فایل هایی که از طریق کامپایل درست میشن ) و این ها میتونن روی هر پروسسر یا سیستم عاملی که runtime .net رو داره اجرا میشه

خوب کامپایلر میاد cil رو میسازه و اون رو داخل dynamic link library میزاره این dll میتونه انتقال پیدا کنه به هر ماشینی و اجرا بشه بدون در نظر گرفتن سیستم عامل یا معماری پروسسورش البته اگر runtime .net روش نصب شده باشه

خوب .net runtime میاد cil رو به کد ماشین تبدیل مکنه

خوب dll چیه ؟ وقتی که یه برنامه مینویسیم در اکثر موارد داریم یه library رو Call میکنیم که یه عملی رو invoke میکنه ، نوشتن توی console یا memory allocation کردن درست کردن thread ، باز کردن file و خیلی فانکشن های دیگه

بعضی از زبان ها مثل c / c++ میان این link ها رو در مرحله ی build کردن میاد اون library رو به صورت statuc وصل میکنه ، و این static link ها شامل به این library ها وقتی که انجام میشن ، برنامه های دیگه نمیتونن ازش استفاده کنن و اگر اون library آپدیت بشه باید برنامه بیاد اون رو Rebuild کنه

یه راه حل منعطف اینه که از dll ها استفاده کنیم ، که میاد یه به صورت public قرارش میدیم و میتونه توسط همه ی برنام ها استفاده بشن ،

و dll ها سایز برنامه رو ککم میکنن و به .net این قابلیت رو میدن که ورژن های جدید رو که bug fix توشون انجام شده رو بیان relase کنن ، بدون این که بخوان کل برنامه رو Rebuild اش کنند

و dll ها معمولا نصب و register میشن با سیستم عامل و میتونن به اشتراک گذاشته بشن ولی اگر برنامه از یه ورژن متفاوت یا dll که مرجعش متفاوت باشه داشته استفاده میکرده که یا dll ای که وصل شده باشه به یه dll دیگه ای که ورژنش متفاوت باشه، اینطوری یه باگی پیش میاد به اسم جهنم dll ها که فقط هم توی .net نیست

خوب کامپایلر یه برنامه است که میاد زبان های سطح بالا رو همه رو تبدیل میکنه به زبان های سطح پایین

کامپایلر هایی که زبان های سطح بالا رو به هم تبدیل میکنن بهشون میگن traspiler و کامپایلر هایی که زبان های سطح پایین رو به زبان های سطح بالا تبدیل میکنن بهشون میگن decompiler

خوب cil یکم سطح زبونش بالاتر از ربان ماشین هستش و CIL میاد یه سری فرض ها رو در مورد معماری پروسسور ها میکنه (رجیستر ها ، دستور ها ، سایز کش و … ) برای همین که بتونه توی بیشترین پلتفرم ها اجرا بشه

قبل از این که .net بخواد اجرا بشه روی پروسسور ، cil میاد کامپایل میکنه به کد ماشین

خوب core clr میاد کامپایل رو در runtime اجرا میکنه که اینطوری dll های clr لازم نیست کامپایل بشه توی پروسسور

ولی کامپیل کردن اینطوری خیلی سنگین میشه و کامپایل کردن کل برنامه هر بار که بخواد اجرا بشه روی سرعت شروع اولیه در هر بار تاثیر میزاره ، این تسک توسط smart compiler میاد و هندل میشه و این طوری میشه که فقط اون قسمتی از کد که قراره ازش استفاده یشه رو فقط کامپایل میکنه و cil میاد just in time کامپایل میشه و به همین دلیل هم jit اسم گذاری شده

در مواقعی که دقیقا میدونیم که معماری سخت افزارمون چیه و سیستم عاملومون چیه و میخوایم کانتینتر docker درست کنیم ، در این زمان ها میتونیم از اثراتی که jit داره رو حذف کنیم با استفاده از aot یا همون ahead of time کامپایلر

میتونیم از aot استفاده کنیم برای حذف کردن و کاهش سایز کد ، ولی یه موق هایی aot کد زیادی رو حذف میکنه

بزرگترین قابلیت aot اینه که compiliton اولیه کد رو انجام میده و کد اجرا میشه بدون این که بخواد وایسته به jit

مدیریت حافظه از یه تکنیکی به اسم grabage collection استفاده میکنه

داستان این تکنیک اینه ککه میاد memory رو track میکنه و اگر قسمتی از حافظه بدون refrence باشه میاد اون رو خالی و پاک میکنه

خوب اینجا c++ باید بیایم دستی بهش حافظه اختصاص بدیم و بعد خودمون هم اون حافظه رو پاک کنیم

خوب توی این مورد size آرایه رو به صورت hardcode نوشتیم ولی میتونیم هم این کار رو نکنیم اگر تعداد المان های ذخیره شده معلوم نباشند و در Runtime ممکنه اون سایز بیشتر بشه برای همین هم میتونیم یه آرایه رو از حافظه بهش اختصاص بدیم ، ولی memory allowcation میتونه یه موقع هایی fail بشه برای همین هم باید یه راهی برای این که این قضیه کامل hanlde بشه

زمانی که کارمون با memory تموم شد باید اون رو خالی کنیم تا بقیه قسمت های برنامه بتونن ازش استفاده کنن

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

خوب توی این کد دیگه نمیاد چک کنه برای این که حافظه داریم و بخوایم اون رو دستی بهش اختصاص بدیم رو در این کد نداریم

اگر حافظه نتونه اختصاص داده بشه garbage collection اجرا میشه و حافظه رو خالی میکنه و دوباره میاد و سعی میکنه که حافظه رو اختصاص بده

اگر collector نتونه حافظه رو برای اون عملیات خالی کنه میاد ارور out of memory exception رو میده تا خوده کاربر بیاد یه راه حلی براش پیدا کنه

بعضی از زبان ها مثل go میاد با استفاده از فانکشن ها ارور ها رو میتونیم بگیریم

ولی .net از exception ها برای نمایش شرایط ارور ها استفاده میشه

زمانی exception ها thron میشن که خطایی اتفاق افتاده ،

کاری که لازمه اینه که بیایم توی کد اون رو بگیریم و catch اش کنیم و بعد هندلش کنیم

البته باید در مکان درستی بیایم و catch اش کنیم

خوب out of memory exception رمانی اتفاق میوقته که .net دیگه نتونسته به اون عملیات حافه اختصاص بده و دیگه برنامه توی این مرحله نمیتونه recover بشه و به اجرا شدنش ادامه بده

خوب توی این حالت کاری که میتونیم بکنیم اینه که ارور رو catch کنیم و بیایم با یه ارور به کاربر نشون بدیم که بیاد memory dump رو انجام بده یا بره ببینه که خطا از کجاست

باید حواسمون باشه که اینجا نباید کدی رو اجرا کنیم که بخواد به برنامه حافظه اختصاص بده چون این کار باعث یه لوپ بینهایت میشه

مدیریت حافظه مجانی نیستش ، یعنی این که یه هزینه ای داره برای اجراش و هزینه اش هم اینه که garbage collection میاد بعضی از قسمت های اجرا شده کد رو فریز میکنه برای این که بتونه حافظه رو به صورت امن reorgnize کنه ، این که کدوم قسمت کد رو میاد این کار رو روش انجام میده غیر قابل پیش بینی و به همین دلیل برای کار های real time خیلی این قضیه ترسناک به نظر میرسه

خوب ما نمیخوایم که pacemaker مون یه موقع هایی وایسته الان یا یه موقع هایی برای این که بخواد حافظه رو خالی کنه ، برای اکثر برنامه ها مزیت استفاده از core clr memory mangement به منظور ساده سازی کد و برنامه و هزینه ی پیاده سازی اونه

بعضی از برنامه نویس ها راههایی رو پیدا کردن که بتونن کنترل کنن حافظه رو در .net و کاهش بدن تاثیرات garbage collector رو

خوب برای ساختن یه console این دستور رو میزنیم

dotnet new console —name HelloDotNet

لیست کامند هایی که میتونیم بزنیم رو توی —help نشون میده

بعد میایم .net رو build میکنیم با dotnet build

وقتی که bild انجام شد یه فولدر bin ساخته میشه

خوب توی فولدر BIN یه سری binery ساخته شده توی build هستش و فایل confiiguration که defualt هستش

وقتی که داریم راجع به assembly حرف میزنیم داریم به اون چیزی که از build شدن بعد از کامپایل شدن رو داریم میگیم نه زبان assembly

و فایل های dll شامل assembly هستند که معمولا به صورت یک به یک به یه پروژه وصل هستند

فایل csproj نمایانگره پروژه و کنترل این که assembly چطور ساخته میشه است

اینجا داره میگه که توی این فولدها یه dll هست که یه public surface area پروژه هستش ولی توش پیاده سازی نیست

برای اطلاعات بیشتر در مورد refrence assembly ها به اون لینکه گفته بریم

میتونیم برنامه رو اجرا کنیم از طریق windows command prompt

نکته : ما داریم برنامه رو اجرا میکنیم از طریق build output folder

برنامه روی سیسیتم ما احرا میشه چون روش sdl .net نصب شده

حالا میخوایم با استفاده از یه nuget به اسم figgle بیایم یه چیزی رو به صورت هنری توی کنسول نمایش بدیم

خوب هر کسی میتونه هر چیزی که میخواد رو توی nuget بزاره یه سری جاهای دیگه هم هستش که میتونیم به اشتراک گذاری انجام بدیم مثل myget ,

خوب میتونیم از این nuget ها استفاده کنیم و این ها با metadata ها روی برنامه انجام میشه

خوب ما توی item group اومدیم package refrence رو اضافه کنیم

خوب نکته ای که هست اینه که برای این که کد کار کنه باید یه سری پکیج دیگه رو هم باید نصب کنیم

figgle font که همون اول نوشته شده داره میگه که توش bundle فونت های هستش که آماده است ازش استفاده کنیم

بعدش standard میشه فونت های استاندارد

برای رندر هم اول پیام رو میزنیم و پارامتر بعدی رو نمیدونم چیه ؟

این جا نکته ای که هست اینه که باید دقت کنیم که وقتی که ما با commad داریم یه پارامتر رو میفرستیم داخل که در اینجا میشه hello .net که توی string هستش رو داریم میفرستیم با args توی برنامه که این قضیه در زمان شروع و اجرای اولیه مورد استفاده قرار میگیره ، حالا داستان اینجاست که اگر اون پارامتر رو خالی بفرستیم میاد اون پیام Usage رو که توی if تعریف کردیم رو نوشون میده چون args داخلش هیچی نیست

خوب توی .net 6 به بعد اومده استایل مینیمال رو پیاده سازی کرده و نتیجه اش این شده که program.cs متد main رو نداره ، ولی طبق convention مد باید شامل top level statment باشه

این قسمت هم خیلی جالبه ، گفته که top level statment لزوما اینطوری نیست که فقط و فقط توی program.cs باشند ما میتونیم اسم فایل رو عوض کنیم و همچنان اون کار میکنه و درسته ولی اگر بیایم و یه فایل cs دیگه رو درست کنیم و یه چیزی که top level statment میشه مثل console.writline نوشته به برنامه به ارور میخوره

چون فقط یه فایل میتونه شامل top leve statment باشه

برای این که program.cs شامل top level statement داره دیگه جز namesapce نیست

خوب namespace برای سازماندهی کردن .net type ها هستش

به طور مثال figgle یه namespace هستش که شامل کلاس هایی هستش برای تولید ascii art ، ما داریم از namespace figgle داریم استفاده میکنیم با استفاده از این کد : using figgle

خوب پکیج و Assembly / dll اسمشون figgle هستش ولی namespace میتونه اسمش متفاوت از این ها

خوب وقتی که برنامه رو اجرا میکنیم یه خط نوشته میشه که brought to you by hello dot net

خوب پراپرتی fulname میاد namespace رو از type name با . جدا کرده

خوب namespace ها اسم هاشون میتونه توشون از dot استفاده کرد که اینطوری میتونیم به صورت سلسله مراتبی از namespace رو درست کنیم

خوب به طور مثال مثلا وقتی که میخوایم از regex استفاده کنیم که بخشی از coreFX هستش که برای اعمال کردن regular expression هستش

خوب اینجا داره اون سلسله مراتب رو نشون میده

تایپ هم که معلومه

خوب .net دو مدل تایپ داره : value و reference که اولی میشه اینطوری که مقدار رو به صورت مستقیم در خودش نگه میداره و دومی میشه ، آدرس جایی که دیتا در اون ذخیره شده

که اون refrence شبیه به pointer ها هستش ولی دقیقا شبیه اش نیست یکم با هم فرق دارن که توی سکشن فصل 10 نوشته فرقشون رو

در C# هر چیزی میتونه مثل یه آبجکت باهاش برخورد بشه (مرجع تمامی reference type ها ) برای این که C# به صورت اتوماتیک عملیات boxing , unboxing رو انجام میده که میشه همون پروسه ی wrap , unwrap کردنش هستش

خوب توی زبان c# همه چی تایپ داره ولی یه مورد خاص هم وجود داره که میشن dynamic type ها که این ها bypass static type checking رو انجام میدن

مثل generic ها و implicit , anoniymous , nullable

خوب using نمایش دهنده اینه که ما میخوایم از اون namespace توی کدمون استفاده کنیم ، با استفاده از namespace ها ما میتونیم به تایپ هایی که توی اون namespace هستش دسترسی پیدا کنیم بدون این که بخوایم اون ها رو qualify کنیم و بررسی کنیم و یا بدون این که بخوایم namespace و type رو بنویسیم

خوب ما میتونیم فقط بنویسیم regx به جای نوشتن system.text.regularexpression.regex و همچنین میتونیم چندین تا type داشته باشیم با یک اسم ولی namespace های متفاوت

خوب اگر خودم برم توی namespace که درست کردم یه تایپ regx بسازم و بخوام ازش توی کدی که اونجا هم از regx که توی coreFX هستش هم هست ، اونجا کامپایلر به ارور میخوره ، چون که میگه که بلاخره تو میخوای از کدوم یکی از این ها استفاده کنی ، فقط اون رو تعیین و تعریف کن

خوب namespace ها میتونن قبل یا بعد از using مورد استفاده قرار بگیرند

خوب توی هر دو حالت ما داریم کلاس bar رو به namespace system.text اضافه میکنیم توی حالت اول اومدیم namespace کلی رو نوشیتم ، چون که داریم از امکاناتی که در namespace regular expression هستش داخل کلاس bar استفاده میکنیم

توی حالت دوم ، اول اومدیم namespace system.txt رو قرار دادیم و بعد اومدیم از regular expression رو using روش زدیم

خوب فرق این دو تا در اینه که دومیه رو ما اومدیم relative قرار دادیم نسبت به اون namespace که اول نوشته شده

این مدل نوشتن کد رو تمیز میکنه ولی از اون طرف اگر چند تا دیگه name space داشته باشیم دیگه نمیدونیم این relative که استفاده کردیم نسبت به کدوم یکی از اون name space ها relative هستش و باعث سردرگمی میشه

خوب میخوایم using رو به صورت explicitly برای namespace پکیج هایی که میخوایم استفاده کنیم. البته این قضیه بالا برای console.writeline درست نیست ، چرا؟ در پایین توضیح میده

خوب writeline که یه static method هستش که توی کلاس console هستش و توی namespace system هستش ، برای همین نیاز نیست که از using system در program.cs استفاده کنیم چون که namespace system به صورت global using توی پروژه استفاده شده

به صورت دیفالت global using معمولا برای net coreFX namespace ها استفاده میشه و میتونیم به صورت implictly هم در csproj هستش اونجایی که زده implicitUsing که مقدارش هم true هستش

ما میتونیم خودمون هم global using رو برای پروژه مون استفاده کنیم اگر namespace ای داریم که توی خیلی از کلاس هامون داره استفاده میشه ،

برای درست کردن global using ها میتونیم بریم تی یکی از کلاس ها و بزنیم global using figgle این یه راهشه و راه دیگه اش اینه که یه فایل جدا برای این gloabl using ها درست کنم مثلا به اسم globalUsing.cs و یه راه دیگه اینه که بیایم توی csproj اضافه اش کنیم ، اینطوری :

1. Removed Figgle.Generator package reference - this package doesn't exist in Figgle 0.6.4

2. Removed the <Using Include="CommandLineParser"/> - CommandLineParser doesn't have a global namespace to import

3. Removed the <Using Include="Figgle.Generator"/> - this namespace doesn't exist

خوب من هر چیزی که توی figgle بود رو اومدم توی gloabl زدم ولی اتفاقی که افتاد اینه که ارور گرفت پروژه مثلا اینجا داره میگه که command line parser به اون صورت global name space نداره برای import

خوب بهترین حالت برای این که پروژه رو build , restor , clean کنیم استفاده کردن از command line ها هستش

خوب global using یه راه خوبیه برای این که بخوایم مقدار کد هامون رو کم کنیم یه راه دیگه هم برای استفاده از using ها استفاده ازشون به صورت static هستش

خوب وقتی که میخوایم به صورت static ازش استفاده کنیم اینطوریه که میتونیم دسترسی به static member های net type ها داشته باشیم بدون این که بخوایم اون type name ها رو بنویسیم ،

به طور مثال اینجا ما نوشتیم using static system.console خوب وقتی که این رو نوشتیم دیگه توی اون کلاس نمیخواد بزنیم console.writeline و فقط کافیه که writeline رو بنویسیم

خوب این کد داره کار میکنه برای این که writeline یه static method هستش توی system.console و standard یه static property هستش توی figgle.figglefont

خوب static using میتونه paired بشه با global using

خوب به طور مثال gobal using static system.console این کار باعث میشه که ما توی مل پروژه میتونیم از writeline استفاده کنیم و دیگه نیاز به نوشتن Console ندارم

یا میتونیم هم این global static using رو بیایم و در یک پروژه وارد کنیم

خوب وقتی که میخوایم از static using ها استفاه کنیم باید دقت به خرج بدیم و توی این کتاب هم فقط جاهایی که خیلی واضح و معلومه که اون عضو در کجا قرار داره اومده از static using استفاده کرده ، مثل همون console.writeline

وقتی که بخوایم به صورت global از چیزی استفاده کنیم :

خوب یه سری نکات به صورت خلاصه :

در program.cs ما یه array از command line argument ها رو که در متغییر args ذخیره میشن

و command line argument ها توی net با space از هم میتونیم جداشون کنیم

میتونیم از qutes برای وصل کردن term ها به هم استفاده کنیم

خوب ولی هیچ آپشن دیگه ای برای این command line ها مثل Action , flags , رو نداره ولی خوب ما میخوایم که یه سری کنترل ها رو روش انجام بدیم مثل conver کردن مقادیر توی تایپ هایی غیر از string

خوب برای این داستان ما یه nuget داریم که یه سری کنترل های بیشتری رو روی کامند هامون داشته باشیم

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

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

بعدی اینه که باید اون message از طریق —help بتونیم ببینیمش

سومی اینه که بتونیم فونتی هم که داره استفاده میشه رو هم تعیین کنیم

خوب convention که داره این command line ها اینه که - برای آپشن های single letter ها استفاده میشه و — دو تا Dash برای logn-form word option ها استفاده میشه که بهشون gnu هم میگن ،

توی سیستم های unix میتونیم تمام کار هایی که میتونیم بکنیم توی فولدر رو با زدن ls یا -a بینینم

توی ویندوز این ها یکم متفاوته ، اینطوریه : ls —all ls -a که اینا جفتشون یکیه

خوب اونهایی که single dash هستند رو میتونیم باهاشون چند تا کامند رو اجرا کنیم ، مثلا توی لینوکس وقتی که میخوایم tar رو extract کنیم میزنیم tar -xvf file.rar خوب x v f مخفف

—extract —verbose —file

خوب برای pars کردن این command line ها یه سری nuget هستش که ما اومدیم از یکیش استفاده کردیم

خوب توی این قسمت میاد nullable رو باید فعال کنیم

بعد بیایم و پیکج های لازم رو اضافه کنیم

خوب اینجا گفته که با item group میتونیم اون ها رو سازماندهی کنیم ولی اجباری نیست

بعد اومده به صورت global static پیکیج ها رو using میکنیم

خوب حالا یه فایل میسازیم به اسم option.cs این فایل میاد و command line رو parse میکنه

خوب اولش میایم و package command line parser رو توی پروژه میزاریم

بعد میایم و توی خود namespace asciiart هم مینویسیم

بعد میایم به جای class از record استفاده کرده ، دلیلش رو جلوتر گفته

بعدش ccustom attribute گذاشتیم که پارامتر اول رو required گذاشتیم

خوب توی پارامتر به جای get زده init که یعنی فقط توی constructor میشه بهش مقدار داد

یه Attribute custom برای این که فونت رو انتخاب کنیم

خوب record چیه ؟ رکورد ها immutable هستند ، خوب command line paramiter ها parse میشن وقتی که برنامه شروع به کار میکنه و بعد توی option قرار میگیره ، بعد از شروع دیگه option محتوی توش نباید تغییر کنه. برای همین بهتره که از record استفاده کنیم

اینجا چیزی که باید بیشتر راجع بهش بخونم اینه که نوشته record ها رو میتونیم ازشون برای equlity check استفاده کنیم

و C# میاد equlity check رو انجام میده و تمامفیلد های record رو با هم مقایسه میکنه

خوب option دو تا پراپرتی داره ، یکی txt هستش که اون متنی که قراره تبدیل بشه به ascii art رو توی خودش نگه میداره ، خوب دلیل این که اومدیم از console application استفاده کردیم این بود که لزومی نداره که اون text اسم پارامتر داشته باشه به جاش فقط با position ای که در command line parameter داره این کار انجام میشه

نکته اینه که —font پارامتر همچنان میتونه قبل از text بیاد به دلیل این که named parameter هستش

خوب پراپرتی font میاد و اسم font رو نگه میداره برای این که asci art بکشه ، خوب font نیازی نیست که حتما تعیین یشه و به همین دلیل این پارامتر اختیاریه , خوب پارامتر font رو میتونیم اینطوری بهش مقدار بدیم با -f و —font

خوب ایده اصلی پراپرتی ها برای اینه که بتونیم کنترل دسترسی داشته باشیم به field ها

خوب feild توی کلاس میشه اون مقادیری که توی scope اون آبجکت یا static scope to class رو داره

اگر بتونیم به feild ها به صورت مستقیم دسترسی پیدا کنیم ، کلاس دیگه نمیدونه و نمیفهمه که چه زمانی و کی به این مقدار دسترسی پیدا کرده یا تغییرش داده

بعضی از برنامه نویس ها این رو تمرین میکنن که برای ساختن فیلد getters , setters بیان و یه سری متد رو درست کنن که بتونیم دسترسی به این feild ها رو کنترل کنند و توی C# اینها رو همه رو در پراپرتی ها قرار دادیم

اگر اون مخفف ها رو پاک کنیم این شکلی میشه :

خوب دقت کنید که value اسمی که رزرو شده برای setter/init

خوب ایونجا نوشته string? که این یعنی اون پارامتر میتونه null باشه

توی msbuild property یه بخشی داشت که نوشته بود nullable true اون برای اینه که توی تنظیمات پروژه به کامپایلر بگیم که ما در مورد پارامتر هایی که null هستند explicit هستیم

برای این که text رو یه پارامتر اجباری کردیم command line parser نمیتونه آبجکت options رو بسازه ، اگر پارامتر text توی command lline parametes نباشه، ولی اگر کامپایلر ندونه میاد یه سری Warning نشون میده که باید یه سری از property ها nullabe بشن

خوب توی C# ما null رو داریم که C# داره روش کار میکنه که به صورت درست هندلش کنه

خوب تمامی operator ها دارن با این nullable type و null کار میکنن

خوب حالا باید بیایم record درست کنیم برای این که مقادیر parse شده رو از command line parameter بگیریم ، برای این کار میایم program.cs رو تغییرش میدیم اینطوری

خوب توی سطر سوم داره میگه که args ها رو میگیره با توجه به کلاس options

اگر درست parse شد مقادیر options رو میفرسته به asciiArt

خوب اگر parse درست نشه این call میشه ،

خوب در نهایت هم با این آپشن ها میاد مینویستش

خوب parse argument متد قبل از argument یه modifier ، این متد از generic argument ها استفاده میکنه ، قبل از پرانتزه

خوب T نمایانگر یه generic type هستش ، parseArgument میاد retrun میکنه یه object از جنس parser reult T

خوب کتابخانه command line parser نمیدونه که چه مقداری رو قراره نگه داره که برای همین هم این که بخواد اون آبجکتی که میخوایم رو برگردونه

خوب generic این قابلیت رو بهمون میده که تعیین کنیم که تایپی که parseArgument از چه مدلی بخونه با چه تایپی و با چه تایپی اون جوابی که میخوایم رو بهمون بده

خوب parse argument , Ienumerable String از مقادیر generic استفاده میکنه که بگه که اون enumerable از نوع string باشه

و IEnumerable یه اینترفیس رو روی array , list , collection ها اجرا میکنه

خوب هر کلاسی که یه اینترفیس داره باید برای پیاده سازی اون کارهای لازمش رو انجام بده

کلاس ها میتونن چندین تا اینترفیس داشته باشن

نکات : کلاس های abstract نمیتونن مستقیم درست بشن یا instantiate بشن به یه آبجکت

کلاس میتونه از یم کلاس abstract ارث بری کنه ولی میتونه از چندین تا interface ارث بری کنه

متد ها یا پراپرتی هایی که implement نشدن توی abstract کلاس ها باید با کلمه ی abstract نشانه گذاری بشن

تحقیق بیشتر در این مورد

صفحه 29


خوب ADO بهمون یه سری قابلیت برای query زدن میده خوب Sql نوشتن خودش یه قابلیته به این دلیل که مدیر دیتابیس میتونه این کوئری ها رو نگاه کنه و چک کنه و بهترشون کنه ولی قضیه اینه که sql نوشتن خیلی زمان بره و این که اون سرعتی هم که قراره خودش رو نشون بده اونقدری نیست که اصلا قابل توجه باشه به جای ado اومده ef رو بیشتر توضیح داده

میگه که دانشی که توی sql یادمیگیریم دقیقا شبیه خیلی از دستورتی هستش که توی linq موجوده. ولی وقتی که میخوایم از ef استفاده کنیم نیازی نیست که inner , outer joint ها رو بدونیم چون خوده ef این ها رو هندل میکنه ولی این رو یادمون باشه که Ef خودش یه abstrraction هستش و معمولا اتفاقی که میفته اینه که این یه سری چیزها به صورت دیفالت توش قرار گرفتن

خوب اینحا داره میگه که میان که یه convert رو از دیتابیس به آبجکت انجام بدن ولی بعضی از Data ها به این راحتی تبدیل به آبجکت نمیشن برای همین میایم از orm ها استفاده میکنیم که کار رو راحت و بهتر انجام بدیم

EF Core handle advanced concepts such as database functions, stored procedures, and mapping object hierarchies to tables

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

همه مدلی هم میتونیم با استفاده از ef بیایم و migration ها رو انجام بدیم که کدمون تبدیل بشه به اون Sql

خوب حالا یه داستانی که هست اینه که micro orm ها اون اوایل که اومده بودن خیلی کار راه بنداز و خوب بودن ، چون که برنامه نویس ها به کوئری ها تسلط بیشتری داشتن به کش و تبدیل داده ها هم همینطور ولی دیگه از .net 6 به بعد اختلافشون با ef همینطوری کمتر و کمتر میشد

حالا میخوایم یه برنامه درست کنیم که کتاب هایی که خوندیم رو طبقه بندی میکنه حالا میخوایم اطلاعات کتاب ها رو هر چی که بهش مربوط هستش رو ذخیره کنیم یا بتونیم اضافه کنیم یا حذف کنیم یا آپدیت کنیم خوب باید یه جوری طراحی کنیم که اگر سرور پوکید دیتا ها رو بشه استفاده کرد و این که قابل scale باشه و پایدار

خوب قبل از این که بخوایم بفهمیم که ef چطوری کار میکنه میتونیم بیایم یه console app بنویسیم

خوب با استفاده از in memory میتونیم بدون این که به یه دیتابیس جدا وصل کنیم ef رو میتونیم کارمون رو راه بندازیم ولی از این مدل دیتابیس نباید در تست استفاده کنیم

خوب اول بیایم یه کلاس کتاب درست کنیم

خوب ef میاد و یه جدول بر اساس entity مون درست میکنه هر جدول دیتابیس معمولا یه کلید داره برای شناسایی هر سطر اگر اون entity یه پرارپتی به اسم id داشته باشه خوده ef میاد اون رو به عنوان PK در نظر میگیریه طبق convention حالا اگر بخوایم مثلا isbn بشه PK میایم از attribute استفاده میکنیم key

خوب book میشه یه جدول

میگه که ef فقط اون entity هایی که به db context ربط دران رو میشناسه و باهاشون کار داره ما متیونیم چندین تا dbcontext داشته باشیم که همشون دارن به یه دیتابیس اشاره میکنن ولی باید حواسمون باشه که تسک هایی به صورت موازی و چند تایی از یه dbcontext استفاده نکنند چون thread safe نیست page 89 org

خوب برای این که بیایم کلاس book رو به dbContext اضافه کنیم باید بیایم یه کلاس جدید بسازیم که از dbcontext ارث بری میکنه

میایم catalogContext و اینطوری میایم به کد اضافه اش میکنیم

اگر از ورژن های 6 یا قدیمی تر استفاده میکردیم احتمالا به یه اروری میخوردیم که books بهش assign value بهش نشده خوده ef ورژنش معمولا جداست ولی بهتره که ورژن Ef با .net همخونی داشته باشه ولی این قانون سفت و سختی نیست از ef 7 به بعد دیگه این قضیه که برای null value ها بخواد ارور بده کنسل شد برای این که میاد مقادیر رو میاد assign میکنه بر اساس dbset based properties

اگر هم اروری بود میشه که از این روش برطرفش کرد فقط کافیه که بهش یه مقدار بدیم

اینجا ما این warning رو داریم

خوب وقتی که که این warning میاد ما چند تا کار میتونیم بکنیم :

اینجا به خاطر پراپرتی title که در کلاس book هستش داره ارور میده و میتونیم برای برطرف کردنش بیایم یا براش ? بزاریم که nullable بشه یا بیایم یه constructor درست کنیم و بگیم که هر وقت که میخواد این کلاس درست بشه باید یه اسم هم بگیریم همون موقع و بهش بدیم

خوب dbset نمایانگره لیست entity ها هستش . خوب entity های ef نمایانگر های abstract هستند و به جدول فقط خلاصه و محدود نمیشن میتونن object های دیگه رو represent کنن مثله database views و همچنین entity ها اسمشون رو به ef core میدن توی این کتاب هر entity دو تا نقش داره هم کلاسه و هم جدول

نکته : onconfiguring متد داره مموری داخل حافظه رو مشخص میکنه و این ، این معنی رو نمیده که dbcontext فقط برای یه مدل یا یه تایپی از دیتابیس ها درست شده - یعنی اینطوری نیست و برای همه مدل دیتابیسی طراحی شده

خوب ما میتونیم خودمون هم option رو به صورت جدا خودمون تعریف کنیم ، اگر بخوایم dbcontext option builder خودمون رو درست کنیم میتونیم option هم درست کنیم منظورشه یه متدی هست که توی بخش 8 میگه برای این که سوییچ کنیم از دیتابیس in memory یا تستی یه دیتا بیس اصلی

خوب برای این که بخوایم Catalog context رو تست کنیم باید بیایم یه سری کار ها رو توی program انجام بدیم :

خوب با استفاده از save changes تمام تغییرات که ایجاد شده رو روی context اعمال میکنیم که اینجا این context مون میشه همون دیتابیسی که روی memory هستش خوب book یه پراپرتی به اسم id داره که با استفاده از convention ها ما اون در نظر گرفتیم که کلید اصلی هستش خوب ef core برای هر entity نیاز داره که یه شاخص داشته باشه یه شاخص خاص برای هر جدول در دیتابیس اکثر دیتابیس های یه قسمتی دارند مخصوص شاخص ها یا ستون شاخص ها که معمولا auto increment مقدارش میره بالا برای هر دیتای جدیدی که واردش میشه خوب اینجا اولیه که وارد میشه id اش 1 هستش دومی 2 و …

وب query ها از linq استفاده میکنن مثلا از order by برای مرتب کردن کتاب ها با استفاده از id شون . حالا اگر بخوایم نزولی مرتبشون کنیم میایم از order by desending استفاده میکنیم

خوب اگر ما Save changes رو بیاریم بعد از query یا همون foreach که زدیم چیزی رو نشون نمیده ، و دلیلش این هست که تا زمانی که این آبجکت هایی که از book ساختیم رو وارد دیتابیس نکنیم که اون چیزی توش نیست که بخواد نمایش بده خوب dbset بهمون دسترسی برای داخل دیتا بیس رو میتونه بده نه اون چیزی توی کد تغییر کرده یا اضافه شده

page 91 کلاس books در database context از نوع enumerable collection هستش. خوب enumerable در این context به معنی چیزی که اینترفیس IEnumarable رو پیاده سازی کرده و میتونه یه itirator داشته باشه که توی آیتم های اون collection دونه به دونه دور بزنه یا بخونتشون یه مدل خاصی از Enumerable ها هستن که بهشون میگیم Queryable ، و اینکه IQerayable مشخصن برای LINQ طراحی شده و یه جورایی میشه extent شده IEnumerable و linq Extention ها کاربرد های زیادی دارن و به چند تا کاتولوگ تقسیم بندی میشن محدود کننده :خوب where هستش که فیلتر میکنه یا محدود میکنه ورودی های enumarable رو به خروجی enumabrable نمایش دهنده : select میاد خروجی رو بر اساس ورودی درست میکنه پارتیشن بندی: take و skip میاد یه قسمت یا یه slice از ورودی enumerable رو به یه خروجی کوچکتری که enumrable هستش تبدیل میکنه به ترتیب کردن : orderby و orderbyDescending میان رورودی ها enumberable رو به خروجی های Enumerable تبدیل میکنن دسته بندی کردن با استفاده از group by انجام میشه چند دسته از enumrable ها رو به یه bucket تبدیل میکنه همسان سازی و متمایز سازی : union , distinct عملیاتی که روی چند سری از دیتا ها انجام میشه و میاد یکسان سازی یا متمایز سازی یا بهم چسبوندن روش انجام میده تبدیل کردن : to list , to array , to dictionary اینها enumerable رو میان materilized میکنن به این معنی که تمام و کل enity رو میان برمیگردونن و لود میکنن و میارن المنت ها : first , first or defualt , last این ها المنت ها رو بر اساس position شون برمیگردونن صحت سنجی : any , all از این ها برای این که ببین المنت ها شرایط و condition های لازم رو دارن استفاغده میشه و خروجی true و false ازش استفاده میشه مجموع سازی sum , count , min از این ها برای انجام محاسبات عددی استفاده میشه

این لیستی که بالا نوشته شده دیگه همه چیو نگفته فقط در حد اینکه یه ایده کلی بگیریم نوشته شده. یه قابلیت دیگه ای هم که داره اینه که میتونیم این ها رو با هم ترکیب کنیم و ازشون استفاده کنیم به طور مثال first or default رو میتونیم روش محدودیت بزاریم و اینطوری دیگه نمیخواد از where استفاده کنیم یه داکیومنت معروفم هست که لینکش اینه

میگه که از interpolated string هها اینجا استفاده شده با استفاده از $ و اینطوری میتونیم مقادیر رو وارد string کنیم

خوب اینجا دیدیم که یه new زدیم و یه آبجکت book رو درست کردیم خوب ابجکت ها با استفاده از constructor درست میشن ولی book اینجا constructor نداره ولی C# اتوماتیک این رو فرض میکنه که constructor داره ولی هیچ argument ای نداره حالا توی c# های قدیمی تر اینطوری باید مینوشتیم :

خوب یه راه برای کوتاه کردن این کد اینه که بیایم برای book یه constructor درست کنیم که یه پارامتر به اسم title داره خوب این کار وقتی که پرارپرتی های زیادی داریم حماقته چون اونجوری باید بیایم برای همشون یه چیزی رو ست کنیم خوب C# یه راه رو میده برای خلاصه سازی که بیایم اون مقادیری که public هستند رو همون اول که دارن ساخته میشن بهشون مقدارش رو بدیم و مقادیر رو بریزیم توی comma seperated list و مقداردهیشون رو انجام بدیم new book() new book {} new book() {}

خوب وقتی که این پروژه رو اجرا میکنیم به چند تا هشدار میخوریم که یکیش اینه که اون پارامتری که داریم میتونه null باشه خوب این هشدار برای یه عملکرد nullable در پروژه هستش که میتونیم اینطوری بر طرفش کنیم : Nullable disable Nullable توی متن نشون داده ولی بهتره که این کار رو نکنیم چون این قانون و عملکرد باعث میشه که بهتر کد بزنیم

خوب اولین تغییری که باید به book بدیم اینه که پرارپرتی id هستش که از نوع int هستش و نمیتونه null باشه مگر اینکه خودمون براش تعیین کنیم که null هم میتونه باشه و بعدیش میرسیم به tittle که string هستش . خوب c# string ها از نوع immutable refrence type ها هستند و میتونن null هم باشن