<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های سپهر اسلامی</title>
        <link>https://virgool.io/feed/@eslamisepehr</link>
        <description>EslamiSepehr.com</description>
        <language>fa</language>
        <pubDate>2026-06-07 08:34:44</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/36722/avatar/bwiSVR.jpg?height=120&amp;width=120</url>
            <title>سپهر اسلامی</title>
            <link>https://virgool.io/@eslamisepehr</link>
        </image>

                    <item>
                <title>C# 9.0: Records - کار با داده‌های تغییر ناپذیر کلاس‌ها</title>
                <link>https://virgool.io/dotnetzoom/c-90-records-%DA%A9%D8%A7%D8%B1-%D8%A8%D8%A7-%D8%AF%D8%A7%D8%AF%D9%87-%D9%87%D8%A7%DB%8C-%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1-%D9%86%D8%A7%D9%BE%D8%B0%DB%8C%D8%B1-%DA%A9%D9%84%D8%A7%D8%B3-%D9%87%D8%A7-bxiisfdwxc4q</link>
                <description>در نوشته‌های قبلی در مورد ویژگی‌های مختلف C# ۹.۰ یاد گرفتیم:دستورات سطح-بالاویژگی‌های Init-onlyدر این نوشته، بیایید به یکی دیگر از ویژگی‌های بسیار جالب C# ۹.۰ که انواع record یا records نامیده می‌شود نگاه کنیم.​کار کردن با داده‌های تغییر ناپذیر بسیار قدرتمند است، اغلب منجر به باگ‌های کمتری می‌شود، و شما را مجبور می‌کند تا اشیا را تبدیل به اشیای جدید کنید به جای اینکه اشیای موجود را اصلاح کنید. توسعه دهندگان #F به این عادت کرده اند، زیرا #F همه چیز را به طور پیش‌فرض به عنوان تغییرناپذیر در نظر می‌گیرد. حالا شما انواع تغییرناپذیر را در C# ۹.۰ نیز دارید، یا به اصطلاح انواع record، یا فقط records نامیده می‌شود. Records کار با داده‌های تغییرناپذیر در #C را برای شما آسان‌تر می‌کند. قبل از این که نگاهی به records در این نوشته بیاندازیم...بیایید با یک کلاس شروع کنیمدر نوشته قبلی شما در مورد ویژگی‌های init-only در C# ۹ یاد گرفتید. من کلاس Firend را با دو خصوصیت FirstName و LastName با ویژگی init-only ایجاد کردم. اگر نمی‌دانید ویژگی init-only چیست، لطفا نوشته قبلی را بخوانید:با ویژگی‌های init-only، شما خصوصیت‌های تغییرناپذیر را به دست می‌آورید. در کلاس Firend در تکه کد بالا، تمام ویژگی‌های آن init-only و بنابراین تغییرناپذیر هستند، شما نمی‌توانید آن‌ها را تغییر دهید. این بدان معناست که هنگام کار با این کلاس، شما مقدار خصوصیت را نمی‌توانید تغییر دهید. ​اگر لازم است چیزی را تغییر دهید، با داده‌های به روز شده یک شی جدید Friend ایجاد می‌کنید. این کاری است که شما هنگام کار با داده‌های تغییر ناپذیر انجام می‌دهید. به جای تغییر یک شی در طول زمان، شما یک شی جدید را در زمان نیاز به تغییر ایجاد می‌کنید. این به این معنی است که شی شما نشان‌دهنده وضعیت داده‌ها در یک نقطه زمانی خاص است.اجازه دهید مثالی از نحوه انجام این کار برایتان بزنم. بیایید یک شی Friend مانند زیر ایجاد کنیم:حالا بیایید فرض کنیم که در نقطه‌ای از برنامه شما نیاز دارید که lastname شی friend را به Mueller تغییر دهید، که یک نام بسیار رایج در آلمان است (‏شما ممکن است گلزنان مشهور فوتبال، Gerd Mueller و Thomas Mueller را بشناسید)‏. همانطور که با داده‌های تغییرناپذیر کار می‌کنید، نمی‌توانید خصوصیت LastName را تغییر دهید. به جای انجام این کار، شما یک شی Friend جدید ایجاد می‌کنید که نشان‌دهنده وضعیت جدید است. شما ممکن است آن شی Friend جدید را مانند تکه کد زیر بسازید. توجه داشته باشید که من چگونه مقدار خصوصیت FirstName را از شی Firend اول به مقدار خصوصیت FirstName شی Friend دوم نسبت می‌دهم:اما زمانی که شما ویژگی‌های بیشتری داشته باشید این رویکرد آزاردهنده است. بیایید یک خصوصیت Middlename را به کلاس Friend اضافه کنیم:حالا شما در تکه کد زیر می‌بینید که ایجاد شی Firend دوم با lastname جدید نیز یک خط کد اضافی برای آن خصوصیت Middlename جدید در پی دارد. به این دلیل است که شما باید این خصوصیت را از شی Firend قدیمی نیز کپی کنید:این بدان معناست که هرچه خصوصیات شما بیشتر باشد، این مسئله سخت‌تر می‌شود. البته شما می‌توانید برخی از منطق کپی با reflection یا serialization پیاده سازی کنید، همچنین می‌توانید از کتابخانه auto-mapping نیز استفاده کنید. اما C# ۹.۰ راه بهتری برای کار با کلاس‌های داده تغییرناپذیر دارد: Records.اولین Record خود را ایجاد کنیدبرای تغییر کلاس Friend به یک record، شما از کلمه‌کلیدی record به جای کلمه‌کلیدی class استفاده می‌کنید. در زیر شما نوع متناظر را به عنوان یک نوع record می‌بینید:ایجاد کپی‌هایی با عبارت Withدر تکه کد زیر شما روشی را می‌بینید که ما در این نوشته برای ایجاد یک شی Firend جدید با lastname جدید استفاده کرده‌ایم. این رویکرد همچنین با نوع record نیز کار می‌کند، اما واقعا کارآمد نیست: شما باید تمام مقادیر خصوصیت‌ها را به صورت دستی از شی اصلی کپی کنید، و اگر آن را به صورت دستی همانند تکه کد زیر بنویسید ممکن است یک خصوصیت را در کد خود فراموش کنید.عبارت with به شما این امکان را می‌دهد که یک شی جدید را با کارایی بیشتری ایجاد کنید. شما آن را در عمل در تکه کد زیر می‌بینید، و آن کد منجر به همان نتیجه‌ای می‌شود که در تکه کد بالا می‌بینید. آخرین دستور در تکه کد زیر از عبارت with برای ایجاد یک شی Friend جدید از شی Friend موجود ذخیره شده در متغیر friend استفاده می‌کند. شما می‌توانید این دستور را اینطور بخوانید: از مقدار خصوصیت‌های شی Friend موجود ذخیره شده در متغیر friend برای ایجاد شی Friend جدید، و تنظیم خصوصیت LastName شی Friend جدید به Mueller استفاده کنید. شی Friend جدیدی که توسط عبارت with با مقدار خصوصیت‌های نشان‌داده‌شده در commentها، متغیر newFriend تولید می‌شود، ذخیره کنید.​همانطور که در تکه کد بالا می‌بینید، عبارت with از یک ترکیب جالب در آغازگر شی برای ایجاد مقادیر جدید خصوصیت‌های مشخص استفاده کرده است. به این معنی است که اگر با آغازگر شی‌ها آشنا باشید، به سرعت با این ترکیب جدید سرعت خواهید گرفت. اما به یاد داشته باشید، عبارت with تنها با انواع record کار می‌کند و نه با کلاس‌های معمولی. ​زمانی که با داده‌های تغییر ناپذیر کار می‌کنید، یک کپی از شی خود را برای یک تغییر ایجاد می‌کنید. این روش به عنوان تغییر غیر-مخرب شناخته می‌شود. به جای داشتن یک شی منفرد که نشان‌دهنده وضعیت در طول زمان است، شما اشیا تغییر‌ناپذیری دارید که هر کدام نشان‌دهنده وضعیت در یک زمان مشخص هستند.بررسی کنید که Recordهایتان برابر هستند یا خیرانواع recordها از reference type هستند و value type مانند structها نیستند. اما متد Equals آن‌ها به طوری اجرا می‌شود که تمام مقادیر خصوصیت‌ها را برای برابری مقایسه می‌کند. در واقع کامپایلر #C، متد  Equals را برای شما ایجاد می‌کند.​ و کامپایلر همچنین overloadهایی برای اپراتورهای == و =! را ایجاد می‌کنید، بنابراین این اپراتورها از متد Equal استفاده می‌کنند. این ویژگی دیگری از انواع record است. این بدان معنی است که شما می‌توانید دو record را با ارزش خصوصیت‌های آن‌ها برای برابری مقایسه کنید. کد در زیر این را در عمل نشان می‌دهد. ابتدا یک شی Friend ایجاد شده و در متغیر friend ذخیره می‌شود. سپس عبارت with برای ایجاد شی Friend دیگر از شی firend موجود استفاده می‌کند. مقدار خصوصیت LastName شی Friend جدید، Mueller قرار داده شده ‌است. سپس دو شی Friend با  عملگر == مقایسه می‌شوند. نتیجه false است چون خصوصیت LastName شی جدید Huber ،Friend نیست و مقدار آن Mueller می‌باشد.بعد از دستور Console.WriteLine شی Friendسوم از شی newFriend ایجاد می‌شود. از عبارت with برای تنظیم مقدار خصوصیت LastName به Huber استفاده می‌شود؛ و شی Friend ایجاد شده در متغیر anotherFriend ذخیره می‌شود. این بدان معنی است که شی ذخیره‌شده در متغیر anotherFriend مقادیر خصوصیت‌ها، مشابه با اولین شی Friend‌ای است که در متغیر friend ذخیره شده است. سپس آن شی Friendاول با شی Friendسوم ذخیره‌شده در متغیر anotherFriend با  عملگر == مقایسه می‌شود. نتیجه دوباره در کنسول با دستور  Console.WriteLine نوشته می‌شود. در این حالت، نتیجه true است، زیرا خصوصیت‌های دو شی Friend شامل مقادیر یکسانی هستند.بررسی برابری یکی دیگر از ویژگی‌های قدرتمند انواع record است. با فراخوانی متد Equals یا با استفاده از عملگر == تمامی مقادیر خصوصیت‌ها را مقایسه می‌کنیم. در واقع، نوع IEquality&lt;T&gt; ،record را پیاده‌سازی می‌کند، در مورد نوع IEquality&lt;Friend&gt; ،Friend را پیاده‌سازی می‌کند.کامپایلر چه چیزی تولید می‌کند؟زمانی که فایل dll. را در برنامه Intermediate Language Disassembler باز کنید (ILDASM.exe - آموزش)، می‌توانید نوع Friend را بررسی کنید تا همه چیزهایی را که کامپایلر #C تولید کرده ببینید. در تصویر زیر می‌توانید نوع رکورد Friend را در Intermediate Language Disassembler ببینید. در واقع کامپایلر #C یک کلاس برای نوع رکورد Friend با خصوصیت‌های LastName ،FirstName و MiddleName ایجاد می‌کند. آنچه که در اینجا مشاهده می‌کنید پیاده‌سازی &lt;IEquatable&lt;Friend می‌باشد. چیز‌های دیگری هم می‌توانید ببینید، برای مثال یک کپی از سازنده که یک شی Friend را دریافت می‌کند، در تصویر زیر در بخش ctor : void(class Friend). نمایش داده شده است.زمانی که بر روی کپی سازنده دو بار کلیک می‌کنید، می‌توانید کد زبان میانی (Intermediate Language Code) را ببینید. کلمه family در خط اول بیانگر این است که سازنده Protected است. سازنده تمام مقدارهای انتقال داده شده به شی Friend را در خصوصیات LastName ،FirstName و MiddleName شی جدید Friend کپی می‌کند.بنابراین، شما می‌توانید فکر کنید که کپی سازنده چیزی شبیه به این در #C است:هنگامی که از عبارت with همانند تکه کد زیر استفاده می‌کنید، کپی سازنده برای ایجاد یک کپی جدید متناظر با شی Friend که با عبارت with مشخص می‌کنید، فراخوانی می‌شود. پس از آن خصوصیت LastName با توجه به آغاز کننده شی که با عبارت with مشخص کردید، مقداردهی می‌شود.در کنار کپی سازنده، کد‌های بیشتری نیز برای انواع record ایجاد می‌شود. آن کد ایجاد شده توسط کامپایلر قسمتی است که تمام جادوها اتفاق می‌افتد. یکی دیگر از ویژگی های مفید تولید شده توسط کامپایلر، متد محافظت شده PrintMembers است. یک StringBuilder را به عنوان یک پارامتر در نظر می‌گیرد و نام و مقدار تمام خصوصیت‌ها را به شی StringBuilder اضافه می‌کند. متد PrintMembers با استفاده از متد بازنویسی شده ToString فراخوانی می‌شود که این هم توسط کامپایلر ایجاد می‌شود. تکه کد زیر، خصوصیت‌های متعلق به شی Friend را در کنسول چاپ می‌کند، Console.WriteLine متد ToString را روی شی Friend فراخوانی می‌کند.خروجی کنسول مانند زیر است. همانطور که مشاهده می کنید، ابتدا نوع چاپ شده و سپس همه خصوصیت‌ها:خلاصهدر این نوشته انواع record که با C# 9.0 معرفی شدند را یاد گرفتید. آن‌ها کار با شی داده‌های تغییرناپذیر در #C را به یک لذت تبدیل می‌کنند. برای توسعه دهندگان #F این چیز جدیدی نیست، اما برای توسعه دهندگان #C پیشرفت بزرگی در این زبان است. with یک دستور قوی و زیبا است که تنها برای records در دسترس است، همچنین records موقعیتی عالی برای تولید خصوصیت‌ها و سازندگان/پایان‌دهندگان هستند.Source: Thomas Claudius Huber - C# 9.0: Records – Work With Immutable Data Classes✅مقالات بیشتر در دات نت زومhttps://t.me/DotNetZoom</description>
                <category>سپهر اسلامی</category>
                <author>سپهر اسلامی</author>
                <pubDate>Sun, 22 Aug 2021 18:09:32 +0430</pubDate>
            </item>
                    <item>
                <title>مقدمه‌ای بر الگوریتم‌های ژنتیک</title>
                <link>https://virgool.io/tarjomyar/%D9%85%D9%82%D8%AF%D9%85%D9%87-%D8%A7%DB%8C-%D8%A8%D8%B1-%D8%A7%D9%84%DA%AF%D9%88%D8%B1%DB%8C%D8%AA%D9%85-%D9%87%D8%A7%DB%8C-%DA%98%D9%86%D8%AA%DB%8C%DA%A9-rmrrdgvcnnth</link>
                <description>الگوریتم ژنتیک یک روش اکتشافی است که از نظریه تکامل طبیعی چارلز داروین الهام‌گرفته شده‌است. این الگوریتم فرآیند انتخاب طبیعی را منعکس می‌کند که در آن افراد شایسته برای تولید مثل به منظور تولید فرزندان نسل بعدی انتخاب می‌شوند. ​مفهوم انتخاب طبیعی​​​​​فرآیند انتخاب طبیعی با انتخاب شایسته‌ترین افراد از یک جمعیت آغاز می‌شود. آن‌ها فرزندهایی تولید می‌کنند که ویژگی‌های والدین را به ارث می‌برند و به نسل بعدی اضافه خواهند شد. اگر والدین تناسب بهتری داشته باشند، فرزندان آن‌ها بهتر از والدین خواهند بود و شانس بیشتری برای زنده ماندن خواهند داشت. این فرآیند تکرار می‌شود و در نهایت، نسلی با شایسته‌ترین افراد پیدا خواهد شد. ​این مفهوم را می توان برای یک مساله جستجو به کار برد. ما مجموعه‌ای از راه‌حل‌ها را برای یک مساله در نظر می‌گیریم و مجموعه‌ای از بهترین راه‌حل‌ها را از میان آن‌ها انتخاب می‌کنیم. ​پنج فاز در یک الگوریتم ژنتیک در نظر گرفته می‌شوند.جمعیت اولیه - Initial populationتابع تناسب - Fitness functionانتخاب - Selectionترکیب - Crossoverجهش - Mutationجمعیت اولیه - Initial populationاین فرآیند با مجموعه‌ای از افراد آغاز می‌شود که جمعیت نامیده می‌شود. هر فرد راه حلی برای مشکلی است که می‌خواهید حل کنید.یک فرد با مجموعه‌ای از پارامترها (‏متغیرها) ‏شناخته‌شده به نام ژن‌ها مشخص می‌شود. ژن‌ها به یک رشته متصل می‌شوند تا یک کروموزوم (‏راه‌حل) ‏را تشکیل دهند. ​در یک الگوریتم ژنتیک، مجموعه ژن‌های یک فرد با استفاده از یک رشته به صورت الفبایی نمایش داده می‌شود. معمولا مقادیر باینری استفاده می‌شوند (‏رشته 1s و 0s)‏. ما می‌گوییم که ژن‌ها را در یک کروموزوم کدگذاری می‌کنیم. ​جمعیت، کروزوم‌ها و ژن‌ها ​​​​​​​​تابع تناسب - Fitness function​​​تابع تناسب تعیین می‌کند که یک فرد چقدر مناسب است (‏توانایی یک فرد برای رقابت با افراد دیگر)‏. این کار به هر فرد امتیاز تناسب می‌دهد. احتمال اینکه یک فرد برای تولید مثل انتخاب شود براساس امتیاز تناسب آن است.انتخاب - Selection​​​​​​​​ایده مرحله انتخاب، گزینش مناسب‌ترین افراد است و به آن‌ها اجازه می‌دهد تا ژن‌های خود را به نسل بعدی منتقل کنند.دو جفت از افراد (‏والدین) ‏براساس امتیاز تناسب انتخاب می‌شوند. افراد با تناسب بالا شانس بیشتری برای انتخاب شدن برای تولید مثل دارند.ترکیب - Crossover​​​​​​​​ترکیب مهم‌ترین مرحله در یک الگوریتم ژنتیک است. برای هر جفت از والدین که باید جفتگیری کنند، یک نقطه ترکیب به طور تصادفی از درون ژن‌ها انتخاب می‌شود. ​به عنوان مثال، نقطه ترکیب را ۳ در نظر بگیرید که در زیر نشان‌داده شده‌است.​​​نقطه ترکیب​​​​​​​​فرزندان با تبادل ژن‌های والدین بین خودشان ایجاد می‌شوند تا به نقطه ترکیب برسند. ​ژن‌های در حال تغییر در میان والدین فرزندان جدید به جمعیت اضافه می‌شوند. ​فرزندان جدید ​​​​​​​جهش - Mutationدر برخی از فرزندان جدید تشکیل شده، برخی از ژن‌های آن‌ها می‌تواند در معرض جهش با احتمال تصادفی پایین قرار گیرند. این نشان می‌دهد که برخی از بیت‌ها در رشته بیتی می‌توانند برگردانده شوند.​​​​​جهش: قبل و بعد​​​​​​​جهش برای حفظ تنوع در جمعیت و جلوگیری از هم‌گرایی زودهنگام رخ می‌دهد. ​پایاناگر جمعیت همگرا شود، ​​​​​​​الگوریتم به پایان می‌رسد (‏فرزندی تولید نمی‌کند که با نسل قبلی تفاوت چشمگیری داشته باشد)‏. همچنین گفته می‌شود که الگوریتم ژنتیک مجموعه‌ای از راه‌حل‌ها را برای مشکل ما فراهم کرده‌است. ​توضیحات​​​​​​​جمعیت یک اندازه ثابت دارد. همانطور که نسل‌های جدید شکل می‌گیرند، افراد با کم‌ترین تناسب می‌میرند و فضایی را برای فرزندان جدید فراهم می‌کنند.توالی فازها برای تولید افراد در هر نسل جدید که بهتر از نسل قبلی هستند، تکرار می‌شود. ​شبه کدSource: Introduction to Genetic Algorithms — Including Example Code | by Vijini Mallawaarachchi | Towards Data Science</description>
                <category>سپهر اسلامی</category>
                <author>سپهر اسلامی</author>
                <pubDate>Fri, 30 Apr 2021 17:20:33 +0430</pubDate>
            </item>
                    <item>
                <title>C# 9.0: init-only - ایجاد خصوصیات تغییر ناپذیر بدون سازنده</title>
                <link>https://virgool.io/dotnetzoom/c-90-%D9%88%DB%8C%DA%98%DA%AF%DB%8C-init-only-%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF-%D8%AE%D8%B5%D9%88%D8%B5%DB%8C%D8%A7%D8%AA-%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1%D9%86%D8%A7%D9%BE%D8%B0%DB%8C%D8%B1-%D8%A8%D8%AF%D9%88%D9%86-%D8%B3%D8%A7%D8%B2%D9%86%D8%AF%D9%87-kl7pfwicfwta</link>
                <description>در نوشته قبلی، شما با جملات سطح-بالا C# 9.0 آشنا شدید. در این نوشته شما با ویژگی دیگری از C# 9.0 آشنا می‌شوید که ویژگی init-only نامیده می‌شود.در نوامبر 2007 مایکروسافت C# 3.0 را با انتشار NET Framework 3.5. معرفی کرد. C# 3.0 بسیاری از مفاهیم جدید، به عنوان مثال زبان پرس و جو یکپارچه (LINQ) را ارائه داده است. همچنین مفهوم قدرتمند مقداردهی اولیه اشیاء را معرفی کرد. این‌ها پایه و اساسی برای ویژگی init-only هستند که با C# 9.0 معرفی شده است، بنابراین بیایید با مقداردهی اولیه اشیاء شروع کنیم.درک مقداردهی اولیه اشیاءفرض کنید شما یک کلاس Friend با دو خصوصیت FirstName و LastName دارید:به طور سنتی، می توانید با فراخوانی سازنده پیش فرض و پس از آن مقداردهی اولیه خصوصیات، یک شئ از Friend را مانند زیر ایجاد کنید:به جای سه عبارت فوق، می‌توانید از یک دستور با مقداردهنده اولیه شئ، همانند تکه کد زیر استفاده کنید. مقداردهی اولیه شئ همچنین سازنده پیش فرض را فراخوانی می‌کند و سپس با فراخوانی setter دو خصوصیت FirstName و LastName را مقداردهی اولیه می‌کند:ایجاد خصوصیات غیرقابل تغییرمشکلی که در مقداردهی اولیه اشیا وجود دارد این است که به شما امکان ایجاد خصوصیات تغییرناپذیر را حداقل تا قبل از C# 9.0 نمی‌دهد. خصوصیات غیرقابل تغییر خصوصیاتی هستند که پس از ایجاد شئ، نمی‌توانید آن را تغییر دهید. اما در این مورد، شما می‌توانید به عنوان مثال خصوصیت FirstName یک Friend را در هر زمان پس از ایجاد شئ Friend تغییر دهید. تکه کد زیر این را نشان می‌دهد:برای ایجاد خصوصیات تغییر ناپذیر، باید یک سازنده مانند تکه کد زیر ایجاد کنید که firstname و lastname را به عنوان پارامتر در نظر بگیرد. توجه داشته باشید که من setter‌های خصوصیت‌ها را حذف کرده‌ام، این بدان معنی است که پس از مقدار دهی اولیه شئ Friend نمی‌توان خصوصیت‌ها را تغییر داد. تعریف فقط یک getter با Auto property به اصطلاح get-only Auto Property نامیده می‌شود. این یک ویژگی است که با 6.0 #C و NET Framework 4.6. در سال 2015 معرفی شده است. Get-only Auto Properties می‌توانند مستقیماً یا مانند تکه کد زیر در سازنده مقداردهی اولیه شوند. این منطق همان فیلدهای فقط‌خواندنی (readonly) است؛ همچنین می‌توان آن‌ها را مستقیماً یا در یک سازنده مقداردهی اولیه کرد.با کلاس Friend که در بالا تعریف شده است، پس از ایجاد شئ Friend نمی‌توانید خصوصیت FirstName یا LastName را تغییر دهید. در زیر این را امتحان می کنم، می‌بینید که خطایی مشاهده می‌شود که می‌گوید خصوصیت FirstName فقط خواندنی است.اکنون مشکل خود را حل کردیم، خصوصیت‌های FirstName و LastName غیرقابل تغییر هستند. اما برای رسیدن به این هدف، ما باید یک سازنده تعریف می‌کردیم.با C# 9.0 می‌توانید خصوصیات تغییر ناپذیری بدون سازنده ایجاد کنید: این مورد با ویژگی init-only ممکن می‌شود.مفهوم ویژگی init-only در C# 9.0در تکه کد زیر یک کلاس Friend را می‌بینید که کاملاً مشابه کلاس Friend تعریف شده در تکه کد قبلی است. و دقیقاً همان کار را می‌کند. اما آیا می‌توانید تفاوتی را مشاهده کنید؟تفاوت در کلمه کلیدی init است که برای Auto Properties استفاده می‌شود. کلمه کلیدی init برای تعریف نوع خاصی از set accessor استفاده می‌شود (این بدان معنی است که اگر از init و set در یک Auto Properties تک استفاده کنید خطا می‌دهد). این خصوصیات اکنون اصطلاحاً به ویژگی init-only گفته می‌شوند. این بدان معناست که شما فقط می‌توانید این خصوصیات را در سازنده مانند تکه کد بالا، یا مستقیماً مانند تکه کد زیر...... یا *drumrolls*… در مقداردهی اولیه شئ ذکر کنید. این باعث می‌شود سازنده‌ای که در بالا استفاده کردیم برای تعریف خصوصیات تغییرناپذیر غیر ضروری باشد. بیایید به این نگاه کنیم.ویژگی init-only و مقداردهی اولیه شئدر تکه کد زیر یک کلاس Friend با ویژگی init-only و بدون سازنده مشاهده می‌کنید. در واقع، این کلاس Friend دقیقاً همان کلاس Friend نشان داده شده در ابتدای این نوشته است. تنها تفاوت در این است که ما از کلمه کلیدی init به جای کلمه کلیدی set برای Auto Properties استفاده کردیم، که ویژگی init-only آن‌ها را می‌سازد.همانطور که قبلاً ذکر شد این بدان معناست که، می‌توانید خصوصیات را فقط در یک سازنده، مستقیماً یا در مقداردهی اولیه شئ، مقداردهی کنید. کلاس Friend ما سازنده ندارد، بنابراین اجازه دهید از مقداردهنده اولیه شئ استفاده کنیم:به خوبی کار می‌کند. اما اکنون نکته مهم این است که پس از ایجاد شئ نمی‌توان خاصیت را تغییر داد. و این قدرت ویژگی init-only است. در تصویر زیر سعی می‌کنم خصوصیت FirstName را بعد از مقداردهی اولیه شئ Friend تنظیم کنم. همانطور که مشاهده می‌کنید، با خطایی روبرو می‌شوم که می‌گوید ویژگی init-only خاصیت FirstName را فقط می‌توان در مقداردهنده اولیه شئ، سازنده یا init accessor اختصاص داد.مقادیری که برای ویژگی init-only لازم نیستلازم به ذکر است که مقادیر برای ویژگی init-only لازم نیستند، آن‌ها اختیاری هستند. همچنین می‌توانید همانطور که با Auto Properties عادی انجام می‌دهید، فقط خصوصیت‌های مورد نظر خود را تنظیم کنید. به عنوان مثال فقط می‌توانید خصوصیت FirstName یک شئ Friend را در تکه کد زیر تنظیم کنید، که کاملاً معتبر است. اما از آنجایی که ما از ویژگی init-only استفاده می‌کنیم، بعد از این دستور شما دیگر فرصتی برای تنظیم خصوصیت LastName ندارید، زیرا خصوصیت‌ها غیرقابل‌تغییر هستند:تنظیم فیلد‌های فقط‌خواندنی (Readonly)همانطور که در حین مقداردهی اولیه شئ، init accessor از ویژگی init-only فراخوانی می‌شود، امکان تنظیم فیلد فقط‌خواندنی (readonly) در init accessor مجاز است، دقیقاً به همان روشی که می‌توانید آن‌ها را در سازنده تنظیم کنید. اگر می‌خواهید مقدار خصوصیت اختصاص داده شده را بررسی کنید، این کار می‌تواند مفید واقع شود. به عنوان مثال اختصاص دادن فضای خالی (whitespace) یا null برای خصوصیت‌های FirstName و LastName معنی چندانی ندارد. بنابراین، می‌توانید کلاس Friend را مانند زیر ایجاد کنید و فیلد‌های فقط‌خواندنی (readonly) را در init accessor‌های خصوصیت‌ها قرار دهید. خصوصیات هنوز تغییرناپذیر هستند، اما اگر در مقداردهی اولیه شئ فضای خالی (whitespace) یا null اختصاص دهید - این تنها راه تنظیم خصوصیات آن کلاس است زیرا هیچ سازنده‌ای تعریف نشده است - یک ArgumentExceptionدریافت می‌کنید.خلاصهویژگی init-only، یک ویژگی قدرتمند است. آن‌ها به شما امکان می‌دهند خصوصیات تغییرناپذیر را بدون تعریف سازنده‌ای که مقادیر خصوصیت اولیه را می‌گیرد، ایجاد کنید. در حالی که تنظیم ویژگی init-only از سازنده کار می‌کند، شما همچنین می‌توانید ویژگی init-only را با مقداردهنده اولیه شئ تنظیم کنید، و بعداً نمی‌توانید آن‌ها را تغییر دهید، زیرا غیرقابل‌تغییر هستند. اگر قصد دارید با داده‌های تغییرناپذیر در #C کار کنید، این یک ویژگی بسیار مفید است.علاوه بر ویژگی init-only، در C# 9.0 تعداد بیشتری ویژگی برای کار با داده‌های تغییرناپذیر وجود دارد: در نوشته بعدی، شما در مورد انواع Record یاد خواهید گرفت.Source: Thomas Claudius Huber - C# 9.0: Init-only Properties – Create Immutable Properties Without Constructor Boilerplate✅مقالات بیشتر در دات نت زومhttps://t.me/DotNetZoom</description>
                <category>سپهر اسلامی</category>
                <author>سپهر اسلامی</author>
                <pubDate>Sat, 27 Feb 2021 23:18:29 +0330</pubDate>
            </item>
                    <item>
                <title>C# 9.0: دستورات سطح-بالا. یا باید بگم: سلام، متد Main کجاست؟</title>
                <link>https://virgool.io/dotnetzoom/c-90-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1%D8%A7%D8%AA-%D8%B3%D8%B7%D8%AD-%D8%A8%D8%A7%D9%84%D8%A7-%DB%8C%D8%A7-%D8%A8%D8%A7%DB%8C%D8%AF-%D8%A8%DA%AF%D9%85-%D8%B3%D9%84%D8%A7%D9%85-%D9%85%D8%AA%D8%AF-main-%DA%A9%D8%AC%D8%A7%D8%B3%D8%AA-z3m6bfj9bmw0</link>
                <description>C# 9.0، ویژگی‌هایی جدید از زبان را معرفی می‌کند، و با این نوشته، من یک سریِ کوچک برای دیدن برخی از ویژگی‌های جدید شروع می‌کنم. بیایید در این نوشته با دستورات سطح-بالا شروع کنیم.زمانی که یک Console application جدید با #C شروع می‌کنید، مقدار زیادی کد تکراری (Boilerplate) دریافت می‌کنید. در زیر شما کد یک برنامه جدید با نام ThomasClaudiusHuber.ConsoleApp مشاهده می‌کنید.اگر در #C تازه‌کار هستید، این برنامه شما را با بسیاری از مفاهیم روبرو خواهد کرد:using directivesnamespacesblocks { }classesstatic methodsvoid return typearray parametersConsole.WriteLine statementدر نسخه‌های قبلی #C و namespace .NET اختیاری بود. همچنین پارامتر args متد Main اختیاری است. شما می‌توانید این برنامه را بدون بلوک namespace و پارامتر args بنویسید:این به این معنی است که از لیست ما، شما می‌توانید namespaces و array paremeters را حذف کنید.using directivesnamespacesblocks { }classesstatic methodsvoid return typearray parametersConsole.WriteLine statementC# 9.0 که با 5 NET. منتشر شد، کلیه ی دستورات را به سطوح بالاتری می رساند که اصطلاحا به آن برنامه سطح-بالا می‌گویند. به این معنی است که شما می‌توانید دستورات را مستقیما در سطح بالای یک فایل بنویسید. نیازی به تعریف کلاس و یا متد ایستای Main نیست. کد زیر Hello World را در Console app که با 9 #C نوشته شده است را نشان می‌دهد:حالا، وقتی به لیست ویژگی‌های که ما در اینجا داریم در مقایسه با Console app اولیه نگاه کنید، به شکل زیر به نظر می‌رسد. فقط using directives و Console.WriteLine statement باقی مانده است:using directivesnamespacesblocks { }classesstatic methodsvoid return typearray parametersConsole.WriteLine statementاین امر روشن می‌کند که برنامه‌های ساده سطح-بالا راهی آسان برای شروع #C هستند. و همچنین مبتدی‌ها مجبور نیستند تمام ویژگی‌های مختلف را از ابتدا یاد بگیرند.هنگامی که از 5 NET. برای پروژه خود استفاده می‌کنید، به صورت پیش‌فرض 9.0 #C به عنوان ورژن زبان می‌باشد. بنابراین با بررسی فایل csproj. و مطمئن شدن از مقدار TargetFramework روی net5.0، اطمینان حاصل کنید که پروژه بر روی 5 NET. اجرا می‌شود:برای استفاده از 5 NET.، شما نیاز به SDK 5 NET. دارید. شما می‌توانید از اینجا دانلود و SDK 5 .NET را نصب کنید.متد Main کجاست؟سوال خوبیه. اگر در گذشته با NET. کار می‌کردید، شما یادگرفته اید که ابتدای هر برنامه NET. متد ایستای Main می‌باشد. اما در یک برنامه سطح-بالا، متد Main وجود ندارد، همانطور که ما فقط این کد را داریم:پس، متد Main ما کجاست؟ بیایید با استفاده از یک ابزار کلاسیک موجود، Intermediate Language Disassembler یا به اختصار ILDASM، ببینیم کد چه چیزی تولید می‌کند. (گزینه‌های قدرتمندتر دیگری مانند ILSpy یا dnSpy وجود دارند، اما در اینجا ILDASM ترجیح داده شده است).اگر 2019 Visual Studio را نصب کرده باشید، یک پوشه 2019 Visual Studio در منوی start پیدا می‌کنید. در آن پوشه، 2019 Command Prompt for Visual Studio وجود دارد.در Developer Command Prompt، فقط ildasm بنویسید و enter را برای باز شدن Intermediate Language Disassembler فشار دهید، همانطور که در عکس زیر می‌توانید می‌بینید. توجه داشته باشید که این کار تنها در Developer Command Prompt قابلیت انجام دارد و نه در command prompt معمول، چون Developer Command Prompt مسیر را مطابق با آن تنظیم می‌کند، بنابراین ILDASM.exe پیدا می‌شود.در Intermediate Language Disassembler، بیایید فایل Console app .dll که از ویژگی برنامه سطح-بالا 9 #C استفاده می‌کند را باز کنیم. در عکس زیر من فایل dll. را باز کرده ام. شما می‌توانید کلاس Program$ و متد ایستای Main$ که در پشت صحنه برای ما تولید شده است را مشاهده کنید. این بدان معنی است که هنوز یک متد ایستای Main وجود دارد، اما اگر یک برنامه سطح-بالا ایجاد کنید که شما متد ایستای Main را به صورت صریح در کدتان تعریف نکنید، به صورت خودکار تولید می‌کند.وقتی که بر روی متد Main$ دوبار کلیک می‌کنید، می‌توانید کد زبان میانی را ببینید. می‌توانید آن را در عکس زیر ببینید. این کد به شما نشان می دهد که کد سطح-بالا دستور Console.WriteLine در واقع به متد Main$ تولید شده، اضافه می‌شود. به عبارت بهتر: تمام دستورات سطح-بالای شما به متد Main$ تولید شده، اضافه می‌شود.آرگومان خط‌فرمانهنگامی که شما به متد خودکار تولید شده Main$ در تصویر بالا نگاه می‌کنید، می‌توانید ببینید که متد Main$، آرگومان مرسوم []string برای خط فرمان را نیز دارد. به عنوان دستورات سطح-بالایی که در فایل یک برنامه سطح-بالا می‌نویسید، که در آن متد Main$ به صورت خودکار ایجاد می‌شود، همچنین می‌توانید به پارامتر []string دسترسی داشته باشید، که به طور مرسوم args نام دارد. بنابراین شما می‌توانید چیزی مانند این در یک برنامه‌ سطح-بالا بنویسید تا آرگومان‌های خط‌فرمان را در کنسول چاپ کنید:تنها و فقط یک فایل با دستورات سطح-بالا می‌تواند وجود داشته باشد.بله، تنها یک متد Main در برنامه‌های NET. می‌تواند وجود داشته باشد. اگر چندین متد Main تعریف کنید، شما با خطای کامپایل مواجه می‌شوید تا زمانی که شما با پرچم main/ نقطه ورود را مشخص کنید.برای یک فایل با دستورات سطح-بالا، متد Main$ تولید شده به عنوان نقطه ورود تنظیم می‌شود. چون تنها فقط یک نقطه ورود برای برنامه NET. وجود دارد، دقیقا فقط یک فایل با دستورات سطح-بالا می‌تواند وجود داشته باشد. بیایید این را آزمایش کنیم: در Console app، یک فایل Customer.cs اضافه کرده‌ام، علاوه بر فایل Program.cs موجود، و تلاش کردم تا از دستورات سطح-بالا به خوبی استفاده کنم. در عکس زیر می‌توانید ببینید که من خطای «فقط یک واحد کامپایل می‌تواند دستورات سطح-بالا داشته باشد» برخورد کرده ام که بدان معنی است که شما از دستورات سطح-بالا فقط در یک فایل از پروژه‌تان می توانید استفاده نمایید.استفاده از Typeها و Namespaceهازمانی که شما namespaceها و/یا typeها را در فایل سطح-بالای برنامه تعریف می‌کنید، این تعاریف باید بعد از تمام دستورات سطح-بالا باشند، در غیر این صورت شما با خطای کامپایل مواجه می‌شوید. برای مثال، به فایل زیر نگاه کنید. Friend type قبل از دستورات سطح-بالا تعریف شده است که منجر به خطا در اولین دستور می‌شود:ترتیب صحیح برای آن برنامه مانند کد زیر می‌باشد. همانطور که می‌بینید، کلاس Friend بعد از دو دستور سطح-بالا برای ایجاد Friend و چاپ firstName از Friend در کنسول می‌باشد:وقتی به کد تولید شده زبان میانی در ILDASM برای تکه کد برنامه بالا نگاه می‌کنیم، می‌توانید ببینید که type Friend به صورت یک فایل جدا ساخته شده است (همچنین می‌توانید کلاس Friend را در یک بلوک namespace قرار دهید). به این معنی است که کامپایلر #C دستورات سطح-بالا را که ابتدا باید تعریف کنید را می‌گیرد، و به متد Main$ تولید شده انتقال می‌دهد و سپس تمام typeها در آن فایل سطح-بالا را همانطور که در هر فایل دیگر #C کامپایل می‌کند، کامپایل می‌کند.خلاصهمن فکر می‌کنم برنامه‌های سطح-بالا افزونه ای مطلوب برای #C هستند. بازی کردن با زبان را بسیار آسان می‌کند. و به ویژه برای پروژه‌های ساده که namespace اضافی، کلاس و متد Main را در کد خود ندارید، بسیار عالی است. NET. به صورت خودکار تمام کد‌های تکراری را برای شما در پشت صحنه‌ها تولید می‌کند، که این عالی است. این ویژگی را دوست دارم.من فکر می‌کنم عیب این کار این است که مبتدیان ممکن است واقعا درک نکنند که در پشت صحنه چه اتفاقی می‌افتد. اما آیا برای شروع با #C لازم است؟ اگر شما فقط یک فایل در پروژه‌تان دارید شاید اینگونه نباشد. اما اگر #C را به یک توسعه دهنده جدید توضیح بدهم، از متد Main شروع می‌کنم، و می‌گویم این تقطه ورود به برنامه است. این چیزی است که همه درک می‌کنند. برنامه شما دقیقا همین جا شروع می‌شود! در صورتی که فایل سطح-بالا باشد، باید بگویم که فایل با دستورات سطح-بالا نقطه ورود به برنامه می‌باشد. و حالا، چه چیزی برای یک مبتدی ساده‌تر است:    الف) پیدا کردن فایل با دستورات سطح-بالا    ب) پیدا کردن متد Mainخب، اگر فقط یک فایل وجود داشته باشد، آسان است و خیلی هم مهم نیست، اما اگر چند فایل و بدون دانستن مفهوم namespace‌ها، کلاس‌ها و متدها سخت است بدانیم یک عبارت سطح-بالا واقعا چیست. بنابراین من فکر می‌کنم قطعا گزینه ب است. پیدا کردن متد Main آسان تر از پیدا کردن یک فایل با دستورات سطح-بالا می‌باشد.بنابراین، من فکر می‌کنم دستورات سطح-بالا برای بازی با زبان در یک فایل خوب هستند، و آن‌ها برای برنامه‌های ساده که در آن فایل‌های زیادی نیاز ندارید عالی هستند. اما اگر شما در نظر دارید که می‌خواهید توسعه دهنده NET. شوید، به شما توصیه می‌کنم از جایی شروع کنید که همه چیز شروع می‌شود: متد Main. :)امیدوارم این نوشته به شما کمک کند تا دستورات جدید سطح-بالا که از ویژگی‌های 9 #C است را بهتر درک کنید. در نوشته بعدی شما درباره خصوصیت init-only یاد خواهید گرفت.Source: Thomas Claudius Huber - C# 9.0: Top-level Statements. Or Should I Say: Hey, Where’s the Main Method?از آقای سیاوش دماری برای کمک و بررسی ترجمه این مقاله تشکر می‌کنم.✅مقالات بیشتر در دات نت زومhttps://t.me/DotNetZoom</description>
                <category>سپهر اسلامی</category>
                <author>سپهر اسلامی</author>
                <pubDate>Fri, 11 Dec 2020 03:19:54 +0330</pubDate>
            </item>
                    <item>
                <title>۹ اصول ارزشمند که باعث می‌شوند با افراد بهتر برخورد کنید</title>
                <link>https://virgool.io/@eslamisepehr/%DB%B9-%D8%A7%D8%B5%D9%88%D9%84-%D8%A7%D8%B1%D8%B2%D8%B4%D9%85%D9%86%D8%AF-%DA%A9%D9%87-%D8%A8%D8%A7%D8%B9%D8%AB-%D9%85%DB%8C%D8%B4%D9%88%D9%86%D8%AF-%D8%A8%D8%A7-%D8%A7%D9%81%D8%B1%D8%A7%D8%AF-%D8%A8%D9%87%D8%AA%D8%B1-%D8%A8%D8%B1%D8%AE%D9%88%D8%B1%D8%AF-%DA%A9%D9%86%DB%8C%D8%AF-dcetdhkma7yt</link>
                <description>اگر می‌خواهید بدانید دیگران چگونه با شما رفتار می‌کنند، بهترین نقطه شروع این است که ببینید چطور با دیگران رفتار می‌کنید. ​و اگر نحوه برخورد با شما را دوست ندارید، تنها یک راه وجود دارد، تغییر رفتار خودتان، زیرا شما نمی‌توانید رفتار فرد دیگری را تغییر دهید. ​روابط مانند یک آینه عمل می‌کنند، که سرانجام این تغییر به نحوه برخورد به شما باز خواهد گشت. ​در اینجا 9 اصل مهم برای به خاطر سپردن نحوه برخورد با دیگران آورده شده‌ است:​​​​۱. به جای قضاوت درباره گذشته افراد، کنار آن‌ها بایستید و به آن‌ها کمک کنید تا آینده خود را بسازند.همه گذشته‌ای دارند. برخی از آن‌ها باعث غرور و افتخار هستند و برخی دیگر بهتر است فراموش شوند. اما گذشته آن‌ها هر چه باشد، مردم تغییر و رشد می‌کنند، بنابراین به جای قضاوت کردن، بایستید و از آن‌ها در حالی که به سمت آینده خود حرکت می‌کنند حمایت کنید. با احترام با آن‌ها رفتار کنید و اجازه بدهید مسیرشان را خودشان بسازند.۲. با کنجکاوی گوش دهید، با صراحت صحبت کنید و به درستی عمل کنید.گوش دادن و کنجکاوی به روابط اجازه رشد می‌دهد. گفتن حقیقت به مردم اجازه می‌دهد که با خود و شما صادق باشند و با صداقت عمل کردن، روابط را در سطح مطلوبی حفظ می‌کند. روابط برای ادامه به کنجکاوی برای رشد، صراحت برای عمیق‌تر کردن و صداقت نیاز دارد. ​۳. با همه با مهربانی رفتار کنید نه به خاطر اینکه آن‌ها مهربان هستند بلکه به این خاطر که شما مهربان هستید.یکی از بزرگ‌ترین هدایایی که می‌توانیم به دیگران بدهیم مهربانی است. اگر کسی نیازمند است، به او کمک کنید. این کار را تنها برای افرادی که دوست دارید و به آن‌ها احترام می‌گذارید انجام ندهید، بلکه برای کسانی که شما را آزار می‌دهند و آن‌هایی که حتی نمی‌شناسید نیز انجام دهید. مهربانی واقعی در عمل آمدن چیزی است که انتظاری در آن نداشته باشد. ​۴. سعی نکنید با کوچک جلوه دادن یک فرد دیگر، خودتان را عالی نشان دهید.​لحظه‌ای که فکر می‌کنید حق دارید دیگران را تحقیر کنید چون بهتر از آن‌ها هستید، ثابت می‌کنید که هیچ قدرتی ندارید. افراد تمایل دارند دیگران را وادار به احساس خود کنند، چه بزرگ و چه کوچک باشد. اگر نمی‌توانید کمک، حمایت و یا عشق ارائه دهید، حداقل هر کاری که توانش را دارید انجام دهید تا به آن‌ها آسیبی نرسد یا احساس کوچک بودن نکنند. با هر کسی که ملاقات می‌کنید با احترام رفتار کنید. ​۵. به یاد داشته باشید، هر فرد داستانی دارند.این ممکن است چیزی باشد که آن‌ها در گذشته تجربه کرده‌اند و یا چیزی که هنوز با آن مواجه هستند، اما به یاد داشته باشید که رفتار در خلا اتفاق نمی‌افتد. هر کس جنگ‌هایی درونی و مسائل مربوط به آن را دارد. قضاوت را کنار بگذارید و در عوض ملاحظاتی را که دوست دارید دریافت کنید، پیشنهاد دهید. ​۶. ما افراد را تصادفا ملاقات نمی‌کنیم.هر کسی را که ملاقات می‌کنید در زندگی شما نقش خواهد داشت، چه بزرگ و چه کوچک باشد. برخی به رشد شما کمک می‌کنند، برخی به شما صدمه می‌زنند و برخی به شما انگیزه می‌دهند که بهتر عمل کنید. در عین حال شما نیز در زندگی آن‌ها نقش دارید. بدانید این مسیر ها به دلیلی پیش روی شما قرار می گیرند و برای افراد اهمیت قائل شوید. ​۷. بهترین معلمان کسانی هستند که به شما ماهی نمی‌دهند بلکه ماهیگیری یاد می‌دهند.هیچ شادی بهتری از کمک کردن به مردم برای دیدن یک چشم انداز برای خودشان و دیدن آن‌ها در سطحی بالاتر از آنچه که خودشان تصور می‌کردند، وجود ندارد. اما این به آن معنی نیست که شما باید آن‌ها را اصلاح یا فعال کنید؛ به جای آن، آن‌ها را به نقاط قوتشان راهنمایی کنید. به آن‌ها پیشنهاد دهید که به روش خودشان حمایت و انگیزه را پیدا کنند و به شما نشان دهند که در چه کاری توانا هستند. تنها کاری که باید انجام دهید این است که به آن‌ها ایمان داشته باشید.۸. هرگز خودتان را برتر نبینید مگر اینکه به کسی کمک کنید.ما دوست داریم زندگی را یک شایسته سالاری بدانیم، بنابراین تحقیر کردن کسی که به اندازه شما موفق، ماهر یا تحصیل‌کرده نیست، آسان است. ​اما نمی‌دانید که این فرد قبلا چه سختی‌هایی را پشت سر گذاشته است و یا در کجا به پایان خواهد رسید. زمان به راحتی می‌تواند مواضع شما را تغییر دهد، پس مطمئن باشید که با وقار با همه رفتار می‌کنید. ​۹. از کسانی که از شما حمایت کرده‌اند قدردانی کنید، کسانی را که به شما صدمه زده‌اند ببخشید، به کسانی که به شما نیاز دارند کمک کنید.کسب ‌و کار بغرنج، زندگی پیچیده و رهبری دشوار است. با همه مردم از جمله خودتان با عشق و شفقت رفتار کنید و در این صورت نمی‌توانید اشتباه کنید. ​با مردم طوری رفتار کنید که می‌خواهید با شما رفتار شود و زندگی بی‌درنگ بهتر خواهد شدReference: Lolly Daskal - 9 Valuable Principles That Will Make You Treat People Better</description>
                <category>سپهر اسلامی</category>
                <author>سپهر اسلامی</author>
                <pubDate>Fri, 28 Feb 2020 00:00:46 +0330</pubDate>
            </item>
            </channel>
</rss>