Advanced .NET Scenario-Based Questions and Answers

 Memory Leak in a WPF Application

Scenario:
A WPF application's memory usage increases over time, even when idle. The application uses event subscriptions, but events are not unsubscribed. How would you diagnose and resolve this issue?

Answer:

  • Cause: Event subscribers hold strong references to publishers. If not unsubscribed, publishers outlive subscribers, keeping them in memory.

  • Diagnosis: Use a memory profiler (e.g., dotMemory, Visual Studio Diagnostic Tools) to inspect object retention graphs. Look for lingering EventHandler references.

  • Fix:

    • Unsubscribe events explicitly when no longer needed.

    • Use weak event patterns (e.g., WeakEventManager).

    csharp
    // Before (leaks):
    publisher.Event += SubscriberMethod;
    
    // Fix:
    publisher.Event -= SubscriberMethod; // Unsubscribe when done
    
    // Or use WeakEventManager:
    WeakEventManager<PublisherType, EventArgs>.AddHandler(publisher, nameof(publisher.Event), SubscriberMethod);

2. Async Deadlock in ASP.NET

Scenario:
An ASP.NET MVC action uses Task.Result to call an async method, causing deadlocks. How would you refactor this?

Answer:

  • Cause: Blocking on async code (e.g., Result/Wait()) in a synchronous context deadlocks due to thread pool exhaustion.

  • Fix: Replace blocking calls with async/await throughout the call chain.

    csharp

    // Before (deadlocks):
    public ActionResult GetData() {
        var data = SomeAsyncMethod().Result;
        return View(data);
    }
    
    // After (async all the way):
    public async Task<ActionResult> GetData() {
        var data = await SomeAsyncMethod();
        return View(data);
    }

3. High CPU in Parallel.ForEach

Scenario:
Parallel.ForEach loop processes a large collection but causes high CPU due to thread contention. How do you optimize it?

Answer:

  • Cause: Shared resources or fine-grained work items cause excessive locking.

  • Optimizations:

    • Use Partitioner.Create to reduce overhead.

    • Avoid shared state; use thread-local variables (ThreadLocal<T>).

    csharp

    var partitioner = Partitioner.Create(data, EnumerablePartitionerOptions.NoBuffering);
    Parallel.ForEach(partitioner, item => Process(item));
    
    // Or use concurrent collections:
    var results = new ConcurrentBag<ResultType>();
    Parallel.ForEach(data, item => results.Add(Process(item)));

4. Captive Dependency in DI

Scenario:
A singleton service in ASP.NET Core injects a scoped service, causing the scoped instance to behave like a singleton. How do you fix this?

Answer:

  • Cause: Scoped services injected into singletons become captive, as their lifespan is extended.

  • Fix: Use IServiceScopeFactory to resolve scoped services within the singleton.

    csharp

    public class SingletonService {
        private readonly IServiceScopeFactory _scopeFactory;
        public SingletonService(IServiceScopeFactory scopeFactory) => _scopeFactory = scopeFactory;
    
        public void Method() {
            using var scope = _scopeFactory.CreateScope();
            var scopedService = scope.ServiceProvider.GetRequiredService<IScopedService>();
            scopedService.DoWork();
        }
    }

5. Optimizing Slow LINQ Queries on Large Data

Scenario:
A LINQ-to-Objects query on a 1-million-item collection is slow. How would you optimize it?

Answer:

  • Optimizations:

    • Use PLINQ (AsParallel()) for CPU-bound work.

    • Replace class with struct and use Span<T> to reduce heap allocations.

    csharp

    // PLINQ example:
    var results = data.AsParallel()
                     .Where(item => item.IsValid)
                     .Select(item => Transform(item))
                     .ToList();
    
    // Span<T> example (for stack-based processing):
    Span<DataItem> span = dataArray.AsSpan();
    foreach (ref var item in span) {
        Process(ref item); // Avoids boxing and heap allocations
    }

6. Secure Password Handling

Scenario:
How would you securely hash passwords in a .NET application to prevent exposure if the database is compromised?

Answer:

  • Best Practice: Use Rfc2898DeriveBytes (PBKDF2) with a high iteration count.

    csharp

    public string HashPassword(string password) {
        byte[] salt = new byte[16];
        using (var rng = RandomNumberGenerator.Create()) {
            rng.GetBytes(salt);
        }
        var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 100000, HashAlgorithmName.SHA256);
        byte[] hash = pbkdf2.GetBytes(32);
        return Convert.ToBase64String(salt) + ":" + Convert.ToBase64String(hash);
    }

No comments:

Post a Comment

check UserExistsParallel Parallel Checks (Faster)

 async function checkUserExistsParallel(email, phone) {   try {     const checks = [];          if (email) {       checks.push(         getD...

Best for you