| کانال توسعه‌دهندگان سی‌شارپ |
1.03K subscribers
19 photos
3 videos
21 links
⭕️ کانال توسعه‌دهندگان سی‌شارپ دولوپیکس

💠 دولوپیکس | جامعه توسعه‌دهندگان ایرانی

💎 @Developix
🚀 Developix.ir

📌 پشتیبانی و تبلیغات:
@DevelopixSupport
Download Telegram
زامارین فرم هم آرشیو شد

👤 MHReza

💎 Channel: @DevelopixCSharp
👍7
اصل Dependency Inversion Principle (DIP) در سی‌شارپ و دات‌نت

‌اصل Dependency Inversion Principle (DIP) یکی از اصول مهم در طراحی نرم‌افزار است که در چارچوب SOLID قرار دارد. این اصل می‌گوید ماژول‌های سطح بالا نباید به ماژول‌های سطح پایین وابسته باشند، بلکه هر دو باید به یک رابط (آبستراکشن) وابسته باشند. این اصل باعث می‌شود کد انعطاف‌پذیرتر باشد و راحت‌تر بشود آن را تست کرد.

مثال بدون استفاده از اینترفیس

در این مثال، یک سرویس ثبت‌نام کاربر و ارسال پیام رو بدون استفاده از اینترفیس درست می‌کنیم که وابستگی مستقیم به کلاس‌های پیاده‌سازی دارد:

// Email sender class
public class EmailSender
{
public void SendEmail(string message)
{
// Logic to send email
Console.WriteLine($"Sending Email: {message}");
}
}

// User registration service class
public class UserRegistrationService
{
private readonly EmailSender _emailSender;

public UserRegistrationService()
{
_emailSender = new EmailSender();
}

public void RegisterUser(string username)
{
// Logic to register user
Console.WriteLine($"User {username} registered.");

// Sending welcome message
_emailSender.SendEmail("Welcome to our service!");
}
}

// Using the service
class Program
{
static void Main(string[] args)
{
UserRegistrationService registrationService = new UserRegistrationService();
registrationService.RegisterUser("JohnDoe");
}
}






در اینجا کلاس UserRegistrationService به‌طور مستقیم به کلاس EmailSender وابسته است و هر تغییری در کلاس EmailSender می‌تواند باعث تغییرات زیادی در کد شود که نگهداری و تست آن را سخت می‌کند.

استفاده از اینترفیس و تزریق وابستگی

حالا با استفاده از اینترفیس و تزریق وابستگی، سرویس ثبت‌نام کاربر و ارسال پیام رو درست می‌کنیم:

// Message sender interface
public interface IMessageSender
{
void SendMessage(string message);
}

// Implementation of the interface for email sending
public class EmailSender : IMessageSender
{
public void SendMessage(string message)
{
// Logic to send email
Console.WriteLine($"Sending Email: {message}");
}
}

// User registration service with dependency injection
public class UserRegistrationService
{
private readonly IMessageSender _messageSender;

public UserRegistrationService(IMessageSender messageSender)
{
_messageSender = messageSender;
}

public void RegisterUser(string username)
{
// Logic to register user
Console.WriteLine($"User {username} registered.");

// Sending welcome message
_messageSender.SendMessage("Welcome to our service!");
}
}

// Using the service
class Program
{
static void Main(string[] args)
{
IMessageSender messageSender = new EmailSender();
UserRegistrationService registrationService = new UserRegistrationService(messageSender);
registrationService.RegisterUser("JohnDoe");
}
}






در این پیاده‌سازی، کلاس UserRegistrationService به‌جای اینکه به یک کلاس خاص وابسته باشد، به یک اینترفیس به‌نام IMessageSender وابسته‌ است. این کار باعث می‌شود کد انعطاف‌پذیرتر باشد و راحت‌تر بتوانیم تغییرات را اعمال کنیم بدون این‌که نیاز به تغییرات زیادی در کد باشد. به‌این‌ترتیب هم تست‌پذیری کد بهتر و هم نگهداری‌ آن راحت‌تر می‌شود.

#تزریق_وابستگی

🔖 #CSharp, #سی_شارپ

👤 Morteza Nazari

💎 Channel: @DevelopixCSharp
Please open Telegram to view this post
VIEW IN TELEGRAM
👍73
تابع بازگشتی چیست؟
تابع بازگشتی یک تابع تو در تو هست که برای رسیدن به نتیجه مورد نظر همواره خودش رو صدا می‌زنه. برای مثال برای به دست آوردن فاکتوریل یک عدد می‌تونیم از تابع بازگشتی زیر استفاده کنیم:
int factorial(int x) {
if (x == 1)
return 1;
else
return x * factorial(x-1);
}



در این تابع هر عددی که وارد کنیم اونقدر این تابع تکرار می‌شه تا عدد به 1 برسه و در نهایت فاکتوریل عدد ورودی رو خروجی می‌ده.

🔖 #CSharp, #سی_شارپ

👤 Morteza Nazari

💎 Channel: @DevelopixCSharp
👍13
🌟 آشنایی با مفهوم lock در سی‌شارپ 🔒

در برنامه‌نویسی، به خصوص در محیط‌های چندنخی (multithreading)، مدیریت همزمانی (Concurrency) یکی از چالش‌های مهم است. برای جلوگیری از بروز مشکلات ناشی از دسترسی همزمان به منابع مشترک، از کلمه کلیدی lock در سی‌شارپ استفاده می‌شود.

📌 کاربرد lock:
- پیشگیری از شرایط رقابتی: زمانی که چند نخ (Thread) سعی می‌کنند به طور همزمان به یک منبع (مانند یک متغیر یا شیء) دسترسی پیدا کنند، ممکن است داده‌ها به درستی پردازش نشوند. lock به ما کمک می‌کند تا فقط یک نخ در یک زمان به یک بخش از کد دسترسی داشته باشد.
- حفظ یکپارچگی داده‌ها: با استفاده از `lock`، می‌توانیم اطمینان حاصل کنیم که تغییرات داده‌ها توسط یک نخ در حال پردازش، با نخ‌های دیگر تداخل نداشته باشد.

✍️ چگونه از lock استفاده کنیم؟

نمونه ساده‌ای از استفاده از lock در سی‌شارپ:

using System;
using System.Threading;

class Program
{
private static int counter = 0;
private static readonly object lockObject = new object();

static void Main()
{
Thread t1 = new Thread(IncrementCounter);
Thread t2 = new Thread(IncrementCounter);

t1.Start();
t2.Start();

t1.Join();
t2.Join();

Console.WriteLine("Final Counter Value: " + counter);
}

static void IncrementCounter()
{
for (int i = 0; i < 1000; i++)
{
lock (lockObject)
{
counter++;
}
}
}
}


📌 این کد چه کاری انجام می‌دهد؟
- دو نخ (t1 و t2) به طور همزمان سعی دارند مقدار متغیر counter را ۱۰۰۰ بار افزایش دهند.
- با استفاده از lock ، فقط یک نخ در هر زمان می‌تواند به کد داخل بلاک lock دسترسی داشته باشد، که به این ترتیب از شرایط رقابتی جلوگیری می‌کند.

📝 نکات مهم:
- از lock برای حفاظت از منابع مشترک استفاده کنید تا از بروز خطاها و مشکلات همزمانی جلوگیری کنید.
- به یاد داشته باشید که استفاده بی‌رویه از lock می‌تواند منجر به کاهش عملکرد برنامه شود؛ بنابراین فقط در مواقع ضروری از آن استفاده کنید.

مزایای lock:
- ساده و آسان: استفاده از lock بسیار ساده است و به راحتی می‌توان آن را در کد پیاده‌سازی کرد.
- محافظت از منابع مشترک: lock به شما کمک می‌کند تا از دسترسی همزمان به منابع جلوگیری کنید و از یکپارچگی داده‌ها اطمینان حاصل کنید.

🔖 #CSharp, #سی_شارپ

👤 ali reza

💎 Channel: @DevelopixCSharp
👍14
در پروژه‌های ASP.NET Core وقتی یک سرویس تعداد زیادی وابستگی دارد، خوانایی، تست‌پذیری و نگهداری کد سخت می‌شود.

ایده‌ی عملی امروز: به‌جای تزریق مستقیم چندین سرویس در یک کلاس، یک Facade یا Aggregate Service بسازید تا زنجیره‌ی وابستگی ساده، قابل تست و خواناتر شود. این رویکرد از Service Locator و constructor bloat جلوگیری می‌کند و مسئولیت‌ها را بهتر جدا می‌کند. 🧩

مثال واقعی: کلاس OrderService که به Inventory، Payment و Notification وابسته است. اول نسخهٔ «بد» با constructor پر از وابستگی‌ها:

<!-- escaped C# code for Telegram -->
public class OrderService
{
private readonly IInventoryService _inventory;
private readonly IPaymentService _payment;
private readonly INotificationService _notification;

public OrderService(IInventoryService inventory, IPaymentService payment, INotificationService notification)
{
_inventory = inventory;
_payment = payment;
_notification = notification;
}

public async Task<bool> PlaceOrderAsync(Order order)
{
if (!await _inventory.ReserveAsync(order)) return false;
var paid = await _payment.ChargeAsync(order);
if (!paid) { await _inventory.ReleaseAsync(order); return false; }
await _notification.SendAsync(order);
return true;
}
}


با الگوی Facade، مجموعهٔ عملیات مرتبط را در یک رابط قرار می‌دهیم تا OrderService ساده شود:

<!-- escaped C# code -->
public interface IOrderProcessor { Task<bool> ProcessAsync(Order order); }

public class OrderProcessor : IOrderProcessor
{
private readonly IInventoryService _inventory;
private readonly IPaymentService _payment;
private readonly INotificationService _notification;

public OrderProcessor(IInventoryService inventory, IPaymentService payment, INotificationService notification) { ... }

public async Task<bool> ProcessAsync(Order order)
{
// همان منطق ترکیبی اینجا قرار می‌گیرد
}
}

public class OrderService
{
private readonly IOrderProcessor _processor;
public OrderService(IOrderProcessor processor) { _processor = processor; }
public Task<bool> PlaceOrderAsync(Order order) => _processor.ProcessAsync(order);
}


نکات عملی:
• با Facade، تست واحد ساده‌تر می‌شود (فقط IOrderProcessor موک می‌شود). 🧪
• مسئولیت‌ها تمیز جدا می‌شوند و هر سرویس کوچک‌تر و تک‌وظیفه‌ای می‌ماند. ✂️
• از تزریق مستقیم تعداد زیادی سرویس در کنترلرها یا سرویس‌های سطح بالا خودداری کنید.

مراجع معتبر: مستندات Microsoft Dependency Injection و الگوهای طراحی در Refactoring.Guru برای جزئیات بیشتر. 📚

شروع به کوچک‌سازی زنجیره‌های تزریق در پروژه کنونی کنید و تغییرات را با تست‌های واحد همراه کنید — تاثیرش را سریع احساس خواهید کرد. 🚀

🔖 #CSharp #سی_شارپ #Facade #DependencyInjection #SOLID #C# #ASP_NET_Core

👤 Developix

💎 Channel: @DevelopixCSharp
2👍1
🔹 یک تکه کد زیر مربوط به CSharp است که روی رفتار closure و async/await در حلقه تاکید دارد.

خروجی نهایی اجرای متد Main چیست؟

(ترتیب و مقدار دقیق خطوطی که در Console چاپ می‌شوند را بنویسید.)

🔖 #CSharp #سی_شارپ

👤 Developix

💎 Channel: @DevelopixCSharp
1
‏Dependency Injection تمیز در ASP.NET Core برای تست‌پذیری بهتر ⚙️

یکی از مهم‌ترین قدم‌ها برای Clean Code در پروژه‌های ASP.NET Core این است که وابستگی‌ها را مستقیم new نکنیم، بلکه از Dependency Injection استفاده کنیم. این کار هم کد را تمیزتر می‌کند، هم تست‌پذیری و امکان تغییر پیاده‌سازی‌ها را بالا می‌برد. 💡

فرض کنید در یک Web API کنترلری دارید که مستقیم وابسته به Service است:

public class OrdersController : ControllerBase
{
private readonly OrderService _orderService;

public OrdersController()
{
_orderService = new OrderService();
}

[HttpGet("api/orders/{id}")]
public async Task<IActionResult> Get(int id)
{
var order = await _orderService.GetByIdAsync(id);
return order is null ? NotFound() : Ok(order);
}
}


این طراحی چند مشکل جدی دارد:

• کنترلر مستقیماً به OrderService Couple شده است.
• تست Unit برای کنترلر سخت است، چون نمی‌توان Mock تزریق کرد.
• در آینده اگر سرویس عوض شود (مثلاً کش اضافه شود)، باید خود کنترلر را تغییر بدهید.

راه تمیزتر این است که یک Interface تعریف کنید و آن را از DI Container تزریق کنید:

public interface IOrderService
{
Task<Order?> GetByIdAsync(int id);
}

public class OrderService : IOrderService
{
private readonly AppDbContext _db;

public OrderService(AppDbContext db)
{
_db = db;
}

public Task<Order?> GetByIdAsync(int id)
=> _db.Orders.FindAsync(id).AsTask();
}


حالا کنترلر فقط Interface را می‌شناسد:

[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
private readonly IOrderService _orderService;

public OrdersController(IOrderService orderService)
{
_orderService = orderService;
}

[HttpGet("{id}")]
public async Task<IActionResult> Get(int id)
{
var order = await _orderService.GetByIdAsync(id);
return order is null ? NotFound() : Ok(order);
}
}


و در Program.cs (یا Startup قدیمی‌ها):

builder.Services.AddScoped<IOrderService, OrderService>();


مزیت‌ها 🧩

• تست‌پذیری بالا: در تست‌ها می‌توان یک FakeOrderService یا Mock تزریق کرد.
• پیاده‌سازی قابل‌تعویض: بدون تغییر کنترلر می‌توانید CachingOrderService اضافه کنید.
• رعایت اصل D از SOLID (Dependency Inversion): وابستگی به Abstraction نه Concrete Class.

برای مطالعه بیشتر، مستندات رسمی مایکروسافت درباره DI در ASP.NET Core خیلی شفاف و به‌روز است:
Microsoft Learn - Dependency injection in ASP.NET Core

قدم‌به‌قدم اگر وابستگی‌های مستقیم را به شکل Interface + DI تبدیل کنید، معماری اپلیکیشن تمیزتر، منعطف‌تر و آماده‌ٔ رشد می‌شود. 🚀

🔖 #CSharp #سی_شارپ #C# #_NET #ASP_NET_Core #Dependency_Injection #SOLID #Clean_Code

👤 Developix

💎 Channel: @DevelopixCSharp
👍31
در نمونه‌کد بالا متد GetUsersByRoleAsync در نسخهٔ اول به‌خاطر فچ‌کردن همه رکوردها در حافظه و بعد فیلتر کردن با Where روی List<T>، هم Memory مصرفی را بالا می‌برد و هم روی دیتابیس‌های بزرگ باعث افت شدید Performance می‌شود. در مقابل، در نسخهٔ دوم با نگه داشتن Query به صورت IQueryable<User> و استفاده از Where قبل از ToListAsync، فیلتر روی خود دیتابیس انجام می‌شود و فقط دادهٔ موردنیاز لود می‌شود. در سناریوهایی که جدول‌های بزرگ دارید یا روی Cloud Database کار می‌کنید، این الگو باعث کاهش چشمگیر حجم دادهٔ منتقل‌شده و بهبود زمان پاسخ متدهای Repository خواهد شد. همچنین با برگرداندن IReadOnlyList<User> به جای List<User>، به Contract بهتری از نظر Encapsulation و جلوگیری از Mutation ناخواسته می‌رسید.

🔖 #CSharp #سی_شارپ

👤 Developix

💎 Channel: @DevelopixCSharp
👍7
استفاده حرفه‌ای از ConfigureAwait(false) در async/await

خیلی وقت‌ها توی کتابخونه‌ها و لایه‌های غیر UI، از async/await استفاده می‌شه ولی ناخواسته Performance و Scale خراب می‌شه؛ فقط به خاطر برنگشتنِ درست به Thread قدیمی.

نکتهٔ مهم اینه: در کدهای غیر UI (مثل لایهٔ Data Access، Service، Library) معمولاً نیازی نیست بعد از await برگردیم به همون SynchronizationContext قبلی. اینجاست که 🧠 ConfigureAwait(false) کمک می‌کنه.

ایده:
هرجا در Library Code هستیم و بعد از await به Context قبلی نیاز نداریم، از ConfigureAwait(false) استفاده کنیم تا:
- Deadlockهای کلاسیک در ASP.NET قدیمی کمتر بشه
- Performance بهتر بشه چون نیاز به Capture/Restore Context نیست

مثال ساده در یک Service غیر UI:
public async Task<UserDto> GetUserAsync(int id)
{
// فرض: این متد توی لایه Service یا Repository صدا زده می‌شه
using var client = new HttpClient();

var response = await client
.GetAsync($"https://api.example.com/users/{id}")
.ConfigureAwait(false);

response.EnsureSuccessStatusCode();

var json = await response.Content
.ReadAsStringAsync()
.ConfigureAwait(false);

return JsonSerializer.Deserialize<UserDto>(json)!;
}


📌 نکات مهم:
- توی UI (WPF, WinForms, MAUI) یا Razor Pages که بعد از await می‌خوای کنترل‌های UI رو آپدیت کنی، از ConfigureAwait(false) استفاده نکن چون به Thread UI برنمی‌گردی.
- در ASP.NET Core به‌خاطر نداشتن SynchronizationContext کلاسیک، مشکل Deadlock خیلی کمتره؛ ولی هنوز هم برای Libraryهای عمومی، استفاده از ConfigureAwait(false) یک Practice خوب حساب می‌شه.
- سعی کن این الگو رو توی کل لایه‌های Library یک‌دست نگه داری تا رفتار کد قابل‌پیش‌بینی بمونه.

برای توضیح رسمی مایکروسافت دربارهٔ async/await و Context:
مستندات async در C# (Microsoft Docs)

امتحان این روش توی Serviceها و Libraryها، مخصوصاً زیر لود بالا، خیلی زود توی لاگ‌ها و Performance خودش رو نشون می‌ده 🚀

🔖 #CSharp #سی_شارپ #CSharp #async #ConfigureAwait #Performance #_NET

👤 Developix

💎 Channel: @DevelopixCSharp
🔥3
این کد C# را در نظر بگیرید:

public class UserService
{
private static HttpClient _client = new HttpClient();

public async Task<string> GetUserNameAsync(int id)
{
_client.BaseAddress = new Uri("https://api.example.com/");
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.Add("X-Request-Id", Guid.NewGuid().ToString());

var response = await _client.GetAsync($"users/{id}");
response.EnsureSuccessStatusCode();

return await response.Content.ReadAsStringAsync();
}
}


در این پیاده‌سازی از static HttpClient استفاده شده، اما همچنان یک Memory Leak / Thread-Safety Anti Pattern جدی در نحوه تنظیم BaseAddress و DefaultRequestHeaders وجود دارد که در سناریوهای چند-ترد یا چند-ریکوئست می‌تواند مشکل‌ساز شود.

چه چیزی باید در این کلاس اصلاح شود تا استفاده از HttpClient هم ایمن‌تر و هم بدون این Anti Pattern باشد؟

🔖 #CSharp #سی_شارپ

👤 Developix

💎 Channel: @DevelopixCSharp
👍31
خیلی از Memory Leakهای ریز تو پروژه‌های #CSharp از یه چیز ساده شروع می‌شن: فراموش‌کردن Dispose روی resourceهایی مثل HttpClient، SqlConnection، فایل‌ها و… 😅

تو دات‌نت جدید، using راحت‌تر و خواناتر شده و اگر درست استفاده بشه، هم کد تمیزتر می‌شه هم از نشت حافظه و handleها جلوگیری می‌کنه. 👇

۱️⃣ الگوی قدیمی using بلاکی
using (var stream = File.OpenRead("data.json"))
using (var reader = new StreamReader(stream))
{
var content = reader.ReadToEnd();
Console.WriteLine(content);
}

اینجا به‌محض خروج از بلاک، هر دو object به‌صورت خودکار Dispose می‌شن.

۲️⃣ الگوی جدید using declaration (از C# 8 به بعد)
برای کاهش nesting و خوانایی بیشتر:
using var stream = File.OpenRead("data.json");
using var reader = new StreamReader(stream);

var content = reader.ReadToEnd();
Console.WriteLine(content);
// در انتهای متد، خودشون Dispose می‌شن

تو این حالت، scopeِ using var کل متده؛ یعنی پایان متد = زمان Dispose. این الگو توی متدهای کوتاه و تمیز عالی جواب می‌ده و از بلاک‌های تو در تو کم می‌کنه. 💡

۳️⃣ نکته مهم در متدهای طولانی
اگر متد خیلی طولانیه و resource فقط تو یه بخش کوچیک لازم می‌شه، بهتره همون الگوی بلاکی رو نگه داری تا resource زودتر آزاد بشه و تا آخر متد تو حافظه نمونه.

۴️⃣ async و IAsyncDisposable
برای کلاس‌هایی که IAsyncDisposable رو پیاده‌سازی می‌کنن (مثلاً بعضی clientهای شبکه):
await using var client = new SomeAsyncClient();
await client.DoWorkAsync();

اینجا در انتهای scope، به‌جای Dispose، متد DisposeAsync صدا زده می‌شه و resourceها به‌شکل async آزاد می‌شن.

جمع‌بندی: استفاده درست از using (به‌خصوص using var و await using) یه راه خیلی ساده و کاربردی برای جلوگیری از Memory Leak و تمیز نگه‌داشتن کده. چند جای پروژه رو که resource سنگین دارن چک و این الگو رو اعمال کن؛ تأثیرش تو performance و پایداری سرویس کاملاً قابل لمسه. 🚀

🔗 مرجع رسمی Microsoft Docs:
https://learn.microsoft.com/dotnet/csharp/language-reference/statements/using

🔖 #CSharp #سی_شارپ #C# #using #dispose #memory #performance #_NET

👤 Developix

💎 Channel: @DevelopixCSharp
1
در نمونه کد بالا در نسخهٔ اول برای محاسبهٔ میانگین یک کالکشن از اعداد، تمام داده‌ها دو بار پیمایش و چندین بار boxing/unboxing انجام می‌شود که هم روی کارایی و هم روی مصرف مموری در سناریوهای پردازش حجم بالای داده تأثیر منفی دارد. با استفاده از Generic و Delegate مناسب (مثل Func<T, double>) می‌توان منطق را طوری پیاده‌سازی کرد که هم type-safe باشد و هم فقط یک بار روی داده‌ها پیمایش شود. کدام نسخه از این پیاده‌سازی در سناریوهای real-world (مثلاً پردازش لاگ، داده‌های سنسور یا تراکنش‌ها) مناسب‌تر است و چرا استفاده از object و is چک‌های پیاپی می‌تواند به یک Anti Pattern در طراحی APIهای عمومی تبدیل شود؟

🔖 #CSharp #سی_شارپ

👤 Developix

💎 Channel: @DevelopixCSharp
👎1
🕒 NodaTime؛ خداحافظ DateTime گیج‌کننده

کار با DateTime و TimeZone در .NET مخصوصاً در پروژه‌های چندمنطقه‌ای واقعاً دردسرسازه؛ از UTC و Local گرفته تا DST و Offsetهای مختلف.

اینجا NodaTime وارد می‌شه؛ یک کتابخانه قدرتمند برای مدیریت زمان و تاریخ که مدلش خیلی شفاف‌تر از DateTime پیش‌فرضه و توی پروژه‌های مالی، رزرو، لاگینگ و سرویس‌های بین‌المللی عالی جواب می‌ده. 🚀

چرا NodaTime؟
• تایپ‌های واضح مثل Instant، LocalDate، LocalDateTime، ZonedDateTime
• پشتیبانی دقیق از IANA Time Zone
• جلوگیری از باگ‌های زمان‌بندی، مخصوصاً اطراف تغییر ساعت (DST)
• API تمیز و قابل تست؛ مخصوصاً برای Domain-Driven Design

نصب با NuGet:
dotnet add package NodaTime


نمونه استفاده ساده:
using NodaTime;

var now = SystemClock.Instance.GetCurrentInstant();
var tz = DateTimeZoneProviders.Tzdb["Europe/Berlin"];
var zoned = now.InZone(tz);

LocalDate invoiceDate = new(2026, 1, 26);
LocalDate dueDate = invoiceDate.PlusDays(14);


برای هر سرویسی که زمان و زمان‌بندی توش مهمه، همراه کردنش با NodaTime جلوی کلی Memory Bug و رفتار عجیب رو می‌گیره. پیشنهاد می‌شه حتماً تو پروژه بعدی امتحان بشه و کم‌کم DateTime خام رو کنار بذاری. 💡

مستندات رسمی:
Website & Docs
GitHub

🔖 #CSharp #سی_شارپ #CSharp #NodaTime #_NET #Time #DateTime #Backend

👤 Developix

💎 Channel: @DevelopixCSharp
👍4
در کد زیر تلاش شده یک Singleton ساده پیاده‌سازی شود، اما هم از نظر Thread-Safety و هم از نظر الگوی طراحی، چند مشکل جدی دارد و در سناریوهای Multi-Thread ممکن است چند نمونه از کلاس ساخته شود.

چه چیزی باید در این پیاده‌سازی اصلاح شود تا الگوی Singleton به‌صورت ایمن و صحیح در سی‌شارپ پیاده‌سازی شود؟

🔖 #CSharp #سی_شارپ

👤 Developix

💎 Channel: @DevelopixCSharp
در نمونه‌کد بالا در نسخه‌ی اشتباه، به‌جای استفاده از LINQ و عملگرهای آماده برای حذف عناصر تکراری، به‌صورت دستی روی لیست حلقه زده شده و برای هر آیتم یک Any() جداگانه روی result صدا زده شده است؛ این کار در سناریوهایی که تعداد رکوردها زیاد است، باعث پیچیدگی زمانی O(n²)، افزایش فشار روی GC و کاهش کارایی می‌شود. در نسخه‌ی اصلاح‌شده با استفاده از GroupBy و انتخاب آخرین آیتم هر گروه (براساس Timestamp)، هم کد خواناتر شده و هم فقط یک بار روی مجموعه اصلی پیمایش انجام می‌شود که در سناریوهای پردازش لاگ یا Events حجیم، مصرف CPU را به‌طور محسوسی کاهش می‌دهد.

کدام رویکرد را برای سناریوهای Real-World با حجم داده بالا منطقی‌تر می‌دانید و چرا در Collections بزرگ، پرهیز از حلقه‌های تو در تو (Nested) تا این حد اهمیت دارد؟

🔖 #CSharp #سی_شارپ

👤 Developix

💎 Channel: @DevelopixCSharp
1👍1
Forwarded from ابر ویراک
ویراک کلود | تجربه‌ی ابری بدون محدودیت ☁️🚀

🎁 ۲۰٪ شارژ هدیه روی اولین واریزی

مزیت‌هایی که واقعاً فرق می‌سازن:
⚡️ پهنای باند 980 مگ
🌐با IP مازاد
⏱️ راه‌اندازی فوری
💳 پرداخت ساعتی
🛡 پشتیبانی ۲۴/۷

💬 هر سوالی داشتی، تیم ما کنارتـه
مناسب استارتاپ‌ها، تیم‌های فنی، تا سازمان‌های بزرگ

همین الان شروع کن و با حداکثر منابع، سریع‌تر رشد کن 👇🏻

📞 تماس سریع: 02191555530
🔗 https://virakcloud.com