<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های hamed hajiloo</title>
        <link>https://virgool.io/feed/@hamedhajiloo96</link>
        <description>حامد حاجیلو هستم، یک NET Full Stack Developer.</description>
        <language>fa</language>
        <pubDate>2026-06-16 16:55:00</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/76312/avatar/vdeP9B.jpeg?height=120&amp;width=120</url>
            <title>hamed hajiloo</title>
            <link>https://virgool.io/@hamedhajiloo96</link>
        </image>

                    <item>
                <title>سفر قهرمانی #C از روزی که به دنیا آمد!</title>
                <link>https://virgool.io/@hamedhajiloo96/%D8%B3%D9%81%D8%B1-%D9%82%D9%87%D8%B1%D9%85%D8%A7%D9%86%DB%8C-c-%D8%A7%D8%B2-%D8%B1%D9%88%D8%B2%DB%8C-%DA%A9%D9%87-%D8%A8%D9%87-%D8%AF%D9%86%DB%8C%D8%A7-%D8%A2%D9%85%D8%AF-uuqz3xg5w0ql</link>
                <description>این قهرمان ما از سال ۲۰۰۲ سفر خودش رو همراه با  Visual Studio 2002 شروع کرد و تا الان (۲۰۲۳) حدود ۱۱ بار آپدیت های جدید و عالی‌ای رو ارائه داد.در اوایل کار یه زبانی شبیه به Java بود و صرفا نسبت به زبان های سطح پایین تنها چیزی که اضافه داشت بحث شی‌گرایی بود، اما در ادامه وارد عصر های مختلفی شد که بد نیست یه نگاهی بهشون بندازیم.عصر نخستین: تبدیل شدن به یک زبان قابل قبولC# 1.0, C# 1.2, C# 2.0توی این عصر زبانی رو مشاهده می‌کنیم که تقریبا مثل بقیه زبان های C-Base هست و تفاوت چندانی نمیکنه. میشه گفت اینجا کار کردن با انواع داده‌ها نسبت به بقیه زبان ها آسون‌تره.با قابلیت های شی‌گرایی شروع کرده و در ادامه به خاطر چالش های نشت حافظه و ... ویژگی های دیگه ای رو هم در ورژن های بعدیش ارائه داد.عصر دوم: اضافه شدن امکانات منحصر بفردC# 3.0 , C# 4.0, C# 5.0حدود سال ۲۰۰۷ قهرمان ما تصمیم گرفت امکانات منحصر بفردی رو ارائه بده که این زبان رو با بقیه هم ردیف های خودش متمایز کنه.این امکانات همراه با NET Framework version 3.5 و Visual Studio 2008 وارد بازار شدند.امکانات نام آشنایی از قبیل Lambda expression ها،Object and collection initializer ها و ... توی این ورژن به سی‌شارپ اضافه شدند.عصر سوم: باز نویسی کامل کامپایلر با سی‌شارپ (Roslyn)C# 6.0سال ۲۰۱۵ سی‌شارپ ۶ همراه با Visual Studio 2015 وارد بازار شد. اینبار سی‌شارپ شروع به اعمال تغییراتی کرد که عمدتا با ذهنیت کد تمیز و ساده همراه بود. از جمله تغییرات مهم هم بازنویسی کامل کامپایلر با خود زبان سی‌شارپ بود.عصر چهارم: رضایت طرفداران کد تمیز و سادهC# 7.0 , C# 7.1 , C# 7.2, C# 7.3استارت تغییرات کوچیک توی ورژن ۶ سی‌شارپ خورده شده بود ولی توی ورژن ۷ به بعد مایکروسافت تمرکز خیلی بیشتری روی این کار داشت و تغییراتش همگی دارای یک هدف مهم بودند. آسون و تمیز بودن کد ها...امکاناتی از قبلی tuple,out,ref و ... از جمله این تغییرات بودند.عصر پنجم:‌ دنیای Cross-Platform، خداحافظی با NullReferenceException و تلاش برای شبیه شدن به زبان های اسکریپت نویسیC# 8.0 , C# 9 , C# 10 , C# 11با اومدن NET Core. روی کار مایکروسافت امکاناتی رو ارائه داده بود که مبتنی بر توانایی های CLR بود.سال ها برنامه نویس ها با خطای NullReferenceException دست و پنجه نرم میکردند ولی حالا با استفاده درست از قابلیت Nullable refrence type ها میشد تا حد قابل قبولی جلوی این اتفاق رو گرفت.در ادامه تغییرات به سمتی میرفت که زبان سی‌شارپ رو شبیه به یک زبان اسکریپت نویسی کرده بود. حالا میشد بدون تعریف کلاس و متد خاصی یک دستور ساده ای رو اجرا کرد. همچنین قابلیت هایی که در pattern maching به سی‌شارپ اضافه شد باعث ساده تر و قابل فهم تر شدن سی‌شارپ میشد. مشاهده جزئیات ورژن های مختلف سی‌شارپ</description>
                <category>hamed hajiloo</category>
                <author>hamed hajiloo</author>
                <pubDate>Thu, 09 Feb 2023 13:10:36 +0330</pubDate>
            </item>
                    <item>
                <title>بهبود مسائل مربوط به Network در NET7.</title>
                <link>https://virgool.io/@hamedhajiloo96/net7-network-ivisrbbolzq1</link>
                <description>یکی از مهم ترین تغییرات در NET7. در بحث Network مشاهده می‌شود که می‌توان آن‌ها را به سه دسته زیر تقسیم بندی کرد. بهبود‌های مربوط به HTTPمعرفی API جدید QUIC امنیت شبکه مسائل مربوط به WebSocket ها بررسی موارد مربوط به HTTPیکی از تاثیر گذارترین تغییرات مدیریت connection هایی هست که attempt failures در آن‌ها رخ داده است.دومین مورد Thread safe شدن HttpHeader ها است.مورد بعدی قابل درک تر شدن خطاهای HTTP/2 و HTTP/3 قابل درک‌تر شدن یعنی چی؟در لایه های پایینی ممکن است خطاهای خاصی رخ دهد. مثلا امکان دارد در HTTP2 خطای REFUSED_STREAM (0x7) رخ دهد. یا در HTTP3 با خطای H3_EXCESSIVE_LOAD (0x0107) مواجه شوید.اینها همگی خطاهایی هستند که برای کاربر در لایه های بالاتر کد معنای خاصی ندارند.در عوض در NET7. ما می‌توانیم با استفاده از HttpProtocolException که در inner exception کلاس HttpRequestException  هست خطاهای مربوطه را catch کنیم.زمانی هم که با ریسپانس های HttpContent کار می‌کنیم، مستقیم می‌توانیم از HttpProtocolException  استفاده کنیم.توضیح مختصری در مورد QUICپروتکل QUIC یا Quick UDP Internet Connections یکی از پروتکل های لایه transport شبکه است که قبلا مایکروسافت پیاده سازی خودش رو در قالب MsQuic ارائه داده بود.بعد ها در NET5. در کدهای خودش هم از این امکان استفاده می‌کرد.در NET7. هم امکان استفاده از این قابلیت با استفاده از System.Net.Quic امکان پذیر شده است.نحوه کارکرد آن نیز در استفاده از سه کلاس زیر خلاصه می‌شود.QuicListener 
QuicConnection 
QuicStreamدر این بین تمرکز اصلی ما بر روی مورد اول یعنی (بهبود‌های مربوط به HTTP) بود و توضیح کوتاهی نیز در مورد مورد QUIC ارائه دادیم،برای مشاهده توضیحات کامل می‌توانید از ? این لینک استفاده کنید.</description>
                <category>hamed hajiloo</category>
                <author>hamed hajiloo</author>
                <pubDate>Sat, 04 Feb 2023 06:21:41 +0330</pubDate>
            </item>
                    <item>
                <title>ویژگی Required، روشی برای مشکلات فعال بودن Nullable</title>
                <link>https://virgool.io/@hamedhajiloo96/c-sharp-11-required-rfck00zm4la8</link>
                <description>اگر ویژگی nullable reference types را فعال کرده باشید، هنگام تعریف متغییر‌ها یا property هایی از نوع reference types، حتما باید مشخص کنید که آیا متغییر‌های شما nullable reference type هستند یا خیر.اگر متغییر ما از نوع nullable باشد، مشکلی وجود ندارد و با چالشی که قرار است در مورد آن صحبت کنیم مواجه نمی‌شویم.Nullable string in C#اما اگر همین متغییر nullable نبود، شما مجبور بودید به یک نحوی مقدار اولیه را در هر شرایطی به این متغییر بدهید.راه حل اول: استفاده از مقدار پیشفرض برای propertyDefault value for propertiesولی این راه حل یک راه حل جامع نیست. راه حل جامع و همه گیر، استفاده از سازنده کلاس است.Set value of properties in constructorراه حل دوم راه حل درستی است ولی شما همه property ها را باید در سازنده کلاس initialize کنید. در این حالت شما هر موقع قصد داشتید از کلاس Person استفاده کنید مجبور هستید از این constructor استفاده کنید.راه حل پیشنهادی Microsoft در C# 11راه حل رهایی از این مشکلات، استفاده از کلمه کلیدی required است.Required propertyدر این حالت اگر جایی بخواهیم از کلاس Teacher یک نمونه بگیریم، حتما باید به صورت object initializer از آن استفاده کنیم و مقدار Name را به آن بدهیم، در غیر اینصورت با خطای زیر مواجه میشویم.Required member must be set in the object initializerو بدین شکل خطا از بین می‌رود.Set required property in object initializerبررسی ویژگی SetsRequiredMembersدر مثال بالا اگر شما یک سازنده داشته باشید و بخواهید از طریق آن مقدار Name را پر کنید چه اتفاقی رخ می‌دهد؟Required member must be set in the object initializerباز هم با همان خطای قبلی مواجه می‌شویم!برای حل این مشکل میتوان از اتربیوت SetsRequiredMembers بالای سازنده (مورد نظر) خود استفاده کرد.SetsRequiredMembersسورس کد</description>
                <category>hamed hajiloo</category>
                <author>hamed hajiloo</author>
                <pubDate>Thu, 08 Dec 2022 21:07:49 +0330</pubDate>
            </item>
                    <item>
                <title>امکان Raw String Literals، یکی از جذاب‌ترین‌های C# 11</title>
                <link>https://virgool.io/@hamedhajiloo96/csharp-11-raw-string-literals-y1olm6ysejsy</link>
                <description> قبل از C# 11 در صورتی که داخل string خود نیاز به double quotation (&quot;) داشتید یا اگر نیاز داشتید به خط بعدی بروید و یا در string interpolation نیاز داشتید در خروجی خود دقیقا مقدار curly bracket ({}) را نمایش دهید، باید آپولو هوا میکردید! مثال ۱: قبل از C# 11 Raw String Literals - Before C# 11خروجیThis is a &quot;quoted text&quot;
 and I go to the new lineبعد از C# 11Raw String Literals - After C# 11مثال۲: قبل از این ورژن گرفتن خروجی زیر کمی پیچیده بود:{
    &quot;name&quot;: &quot;Hamed&quot;
}اما در این ورژن به سادگی زیر میتوان این خروجی را به دست آورد:Raw String Literals for Json - C# 11 نحوه استفاده از string interpolation در این قابلیت جدید نیز کمی متفاوت است.Raw String Literals for string interpolation - C# 11همانطور که مشاهده میکنید ۲ بار از $ و {} استفاده شده است.خروجیYou are at {2, 2}یکی دیگر از امکانات بسیار مفیدی که در این ویژگی C# 11 به ارمغان رسیده است، شروع Indentation از جایی هست که خط اول شروع شده است. به مثال زیر از C# 10 دقت کنید.Raw String Literals for indented strings - Before C# 11 همانطور که (احتمالا) میدانید، خروجی این کد یک string ای است که از سمت چپ tab خورده است. اگر هم قصد داشته باشید این tab اتفاق نیفتد، حتما باید متن داخل string را از ابتدای کد شروع کنید. خوانایی این کد جالب نیست. در C# 11 شروع محتوای این string از جایی هست که &quot;&quot;&quot; شروع می‌شود. برای مثال اگر بخواهید این tab در C# 11 وجود نداشته باشد، می‌توانید از کد زیر استفاده کنید. در کد زیر شروع کد از جایی هست که &quot;&quot;&quot; شروع شده است، در نتیجه هیچ فاصله ای از سمت چپ وجود نخواهد داشت.Raw String Literals for indented strings - After C# 11 سورس کد مقاله</description>
                <category>hamed hajiloo</category>
                <author>hamed hajiloo</author>
                <pubDate>Thu, 08 Dec 2022 14:45:02 +0330</pubDate>
            </item>
                    <item>
                <title>استفاده از Bit platform برای ساخت یک پروژه Blazor</title>
                <link>https://virgool.io/@hamedhajiloo96/blazor-bit-platform-rafwzvn0rf4x</link>
                <description>احتمالا هنگام ایجاد یک پروژه #Blazor ای با سوال‌ها و چالش‌های متعددی روبرو شدید.? کندی سرعت لود اولیه سایت در حالت Wasm به دلیل دانلود فایل های مورد نیاز.? مشکلات سئو.? مشکلات ایجاد شده به واسطه تعداد بالای کاربر در آن واحد در حالت Blazor Server.? دردسر زیاد زمانی که تصمیم به سوییچ کردن بین حالت‌های مختلف Blazor داشته باشید.? و مشکلات احتمالی دیگر...تمام این مسائل در Bit platform  مورد بررسی قرار گرفته و شما می‌توانید از پروژه Todo Template به عنوان template اولیه خود استفاده کنید.همچنین در داکیومنت Todo template   توضیحات مختصر و مفیدی مبنی بر نحوه کانفیگ پروژه ارائه شده است که در صورت استفاده از آن می‌توانید اکثر مشکلات مطرح شده را حل کنید.? در حالت کلی هم در اکثر مواقع شما نیاز به یک پروژه Blazor Webassembly ای دارید که Prerendering دارد. یعنی کانفیگ زیر:&lt;BlazorMode&gt;BlazorWebAssembly&lt;/BlazorMode&gt;&lt;WebAppDeploymentType&gt;SSR&lt;/WebAppDeploymentType&gt;? در این حالت شما یک PWA ای دارید که حالت Prerendering دارد و چالش سرعت اولیه لود سایت در همین جا حل می‌شود. ? به خاطر کانفیگ‌هایی که در این Template وجود دارد و در داکیومنت به آن اشاره شده است سئو سایت در بهینه‌ترین حالت خود قرار می‌گیرد.? با یک کانفیگ بسیار ساده می‌توانید بین سه حالت BlazorServer, BlazorWebAssembly و BlazorHybrid سوئیچ کنید.? می‌توانید با یک کد خروجی Web,Android, IOS, Windows و ... داشته باشید.? در نهایت اگه به نظرتون #BitPlatform ابزار مفیدی بود با ستاره دادن و Contribute در Github  و اشتراک گزاری این مطلب می‌تونید از این ابزار حمایت کنید.</description>
                <category>hamed hajiloo</category>
                <author>hamed hajiloo</author>
                <pubDate>Tue, 26 Jul 2022 14:25:32 +0430</pubDate>
            </item>
                    <item>
                <title>معرفی System.Threading.Channels</title>
                <link>https://virgool.io/@hamedhajiloo96/system-threading-channels-z1kx0mctp7gp</link>
                <description>در دنیای واقعی مثال های زیادی راجع به مسائل مربوط به چرخه تولید به مصرف وجود دارد.مثلا در رستوران ها از زمان آماده سازی لوازم گرفته تا هنگام پخت غذا و تحویل سفارش کارهایی انجام میشود تا درخواست مشتری انجام شود، روش های مختلفی برای این کار وجود دارد:هر قسمت منتظر این بماند که شخصی اعلام نیاز کند و سپس آن قسمت شروع به انجام وظیفه خود کند، که در این جا مشتری زمان بسیار زیادی را منتظر میماند.(پرفورمنس پایین)تمام قسمت ها از قبل سفارشات آن روز را آماده داشته باشند. با این شرایط مشکلاتی از قبیل سرد شدن سفارش, نبود جا برای نگهداری سفارش و ... به وجود می آید.(استفاده غیر بهینه از منابع)یک رویه مشخصی از چرخه تولید وجود داشته باشد که با تعداد و سرعت محاسبه شده ای هر قسمت از چرخه وظیفه خود را انجام دهد و محصول تولیدی را تحویل عنصر بعدی چرخه دهد.(پرفورمنس بالا و استفاده بهینه از منابع)چرخه تولید به مصرف در برنامه نویسیمثالی که خدمتتان ارائه شد در برنامه نویسی کاربرد فراوانی دارد و آن را تحت عنوان مسائل &quot;Producer/consumer&quot; میشناسیم.Producer/consumerفرض کنید سیستم ایمیل مارکتینگ شما قرار است یک میلیون کاربر را در حافظه لود کند و سپس به همه آن ها ایمیل ارسال کند. از زمانی که شما این کاربر ها را از دیتابیس لود میکنید هزینه بالایی بابت کوئری سنگین متحمل میشوید و همچنین بعد از لود کردن هم نگهداری این تعداد در حافظه باعث اشغال شدن مقدار زیادی از حافظه میشود. (هر چند عملیات با موفقیت انجام میشود ولی بهینه نیست!)راه حل بهتر استفاده از سیستمی مثل چرخه رستورانی هست که مثال زده شد.میتوانیم از Queue استفاده کنیم. سمت تولید کنند داده, داده را داخل صف قرار دهد و مصرف کننده از سمت دیگر از این داده استفاده کند.در اینجا چالش های دیگری هم وجود دارد. مثلا مصرف کننده باید مطلع شود که مقداری درون صف هست و یا این که هر موقع تولید کننده دیگر داده ای برای تولید نداشت باید به مصرف کننده این موضوع رو اطلاع دهد و قاعدتا این که سمت مصرف کننده مدام از صف بپرسد که آیا داده ای وجود دارد ایده خوبی نیست.      برای حل این چالش هم میتوان از semaphoreslim استفاده کرد.چالش دیگری که وجود دارد این است که اگر برنامه ما به صورت موازی در حال کار کردن بود، بایستی صف های موجود در هر Thread از دسترسی توسط Thread دیگر مصون بمانند. (Thread safe)همانطور که مشاهده میکنید با در نظر گرفتن این موارد میتوانید یک سیستم صف خوب برای پروژه خود ایجاد کنید یا این که از System.Threading.Channels استفاده کنید. زیرا تمام چالش های مطرح شده در این کلاس مدیریت شده است.معرفی System.Threading.Channelsدر این فضای نام، کلاس استاتیک Channel وجود دارد که برای ساخت یک چنل باید از یکی از متد های CreateBounded و CreateUnbounded استفاده کرد(هر کدام از این ها یک overload دیگر هم دارند که BoundedChannelOptions یا UnboundedChannelOptions به عنوان ورودی میگیرند که در ادامه راجع به هر کدام صحبت میشود.public static Channel&lt;T&gt; CreateBounded&lt;T&gt;(int capacity) {}
public static Channel&lt;T&gt; CreateBounded&lt;T&gt;(BoundedChannelOptions options) {}
public static Channel&lt;T&gt; CreateUnbounded&lt;T&gt;() {}
public static Channel&lt;T&gt; CreateUnbounded&lt;T&gt;(UnboundedChannelOptions options) {}تابع CreateBounded یک capacity به عنوان ماکسیمم سایز صف در نظر میگیرد در حالی که با استفاده از تابع CreateUnbounded هیچ محدودیتی برای سایز صف وجود ندارد (در این جا باید توجه داشت که اگر مقدار زیادی داده وجود دارد رم زیادی اشغال میشود و این موضوع خود عاملیست برای استفاده غیر صحیح از منابع)اگر میخواهید از CreateBounded استفاده کنید، باید مشخص کنید که اگر صف پر بود چه استراتژی باید در نظر گرفته شود(منتظر بمانیم یا ...)؟ در اینجا میتوانیم از BoundedChannelOptions استفاده کنیم.هر دوی کلاس های BoundedChannelOptions  و UnboundedChannelOptions از کلاس ChannelOptions ارث بری میکنند. UnboundedChannelOptions  به جز سه پراپرتی کلاس پدر ، چیز اضافی ای ندارد. ولی کلاس BoundedChannelOptions دو پراپرتی اضافه تر نیز دارد که به معرفی آنها میپردازیم.Channel.CreateBounded&lt;T&gt;(new BoundedChannelOptions(capacity)
{
    FullMode = BoundedChannelFullMode.Wait
});پراپرتی FullMode میتواند 4 مقدار مختلف بگیرد که کاملا مشخص است هر کدام از این مقادیر چه کاری انجام میدهند. public enum BoundedChannelFullMode
  {
        Wait, 
        DropNewest,
        DropOldest,
        DropWrite
  }حالت پیشفرض در اینجا wait است.هم چنین با پراپرتی های دیگر این کلاس شما میتوانید مشخص کنید که فقط یک نفر میتواند داخل چنل، داده قرار دهد و بخواند یا بیشتر.چگونه بر روی Channel داده قرار دهیم یا از آن بخوانیم؟برای خواندن یا نوشتن بر روی چنل باید از دو کلاس ChannelReader و ChannelWriter استفاده کرد.Channel&lt;T&gt; channel = Channel.CreateUnbounded&lt;T&gt;();

ChannelReader&lt;T&gt; reader = channel.Reader;
ChannelWriter&lt;T&gt; writer = channel.Writer;بهترین روش قرار دادن داده بر روی چنل استفاده از متد WriteAsync است. برای متوجه شدن این موضوع میتوانیم پیاده سازی این متد را ببینیم.public async ValueTask WriteAsync(T item, CancellationToken cancellationToken)
{
    while (await WaitToWriteAsync(cancellationToken).ConfigureAwait(false))
        if (TryWrite(item))
            return;

    throw new ChannelCompletedException();
}همانطور که مشاهده میکنید اگر به هر دلیلی مثل پر بودن صف و ... در آن لحظه نتوانستیم مقداری داخل صف قرار دهیم، منتظر میمانیم تا صف این اجازه را به ما بدهد.همچنین برای خواندن از روی صف نیز این موضوع صادق است.public virtual async IAsyncEnumerable&lt;T&gt; ReadAllAsync(
    [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
    while (await WaitToReadAsync(cancellationToken).ConfigureAwait(false))
        while (TryRead(out T item))
            yield return item;
} اعلام پایان کار Producer:همانطور که مشاهده میکنید consumer همیشه منتظر خواندن داده میماند، پس قاعدتا Producer پس از پایان کار باید اعلام کند که دیگر داده ای برای نوشتن ندارد. در نتیجه در کلاس Writer از متد Complete میتوانیم برای انجام این کار استفاده کنیم.جمع بندی:برای به وجود آوردن بهترین حالت چه از لحاظ پرفورمنسی و چه از لحاظ استفاده صحیح منابع، از CreateBounded استفاده کرده و از متد های زیر برای خواندن و نوشتن بر روی آن.//1
await channel.Writer.WriteAsync(item);


//2
channel.Writer.Complete();

//3
 await foreach (var item in channel.Reader.ReadAllAsync())
{
 Use(item);
}نمونه ساده ای از نحوه استفاده کردن از System.Threading.Channels را میتوانید در گیت هاب من مشاهده بفرمایید.</description>
                <category>hamed hajiloo</category>
                <author>hamed hajiloo</author>
                <pubDate>Sat, 10 Apr 2021 12:43:55 +0430</pubDate>
            </item>
            </channel>
</rss>