ItTechGenie-Subject - Generics & Delegates (Questions Only)

C# Question Bank

Generics & Delegates | 10 Questions (7 Moderate + 3 High)

Students should implement ONLY the TODO methods inside each code block. This is a standalone preview HTML (your real site uses _Layout.cshtml).
Moderate: 7 High: 3 Focus: Generic methods/classes, constraints, Func/Predicate, multicast delegates, variance, events, retry utility
1

Generic Swap Utility (Type-safe)

Generics Generic Method ref Moderate

You are building a small utility library for an internal console tool. Implement a **generic Swap<T>** method so any two variables of the same type can be swapped safely. ✅ Student task: - Implement only the TODO method Swap<T>(ref T a, ref T b). - Do not change Main().

Boilerplate C# console program (students implement only TODO methods) Ctrl+C
using System; // Console, basic types

namespace ItTechGenie.M1.GenericsDelegates.Q1
{
    public class Program
    {
        public static void Main()
        {
            int a = 10;                   // first integer
            int b = 20;                   // second integer
            Console.WriteLine($"Before: a={a}, b={b}"); // print before swap

            Utils.Swap(ref a, ref b);     // swap integers using generic method

            Console.WriteLine($"After : a={a}, b={b}"); // print after swap

            string x = "Hello";           // first string
            string y = "World";           // second string
            Console.WriteLine($"Before: x={x}, y={y}"); // print before swap

            Utils.Swap(ref x, ref y);     // swap strings using same method

            Console.WriteLine($"After : x={x}, y={y}"); // print after swap
        }
    }

    public static class Utils
    {
        // ✅ TODO: Student must implement only this method
        // Goal: swap two variables of type T using a temporary variable.
        public static void Swap<T>(ref T a, ref T b)
        {
            // TODO: Write your code here
            throw new NotImplementedException(); // remove after implementing
        }
    }
}
2

Generic Repository: Add & GetAll

Generics Generic Class List<T> Moderate

A team needs a small in-memory repository during early development (before database integration). Create a **generic repository** that can store ANY entity type. ✅ Student task: - Implement Add(T item) and GetAll() methods only. - Keep the internal list private and do not expose it directly.

Boilerplate C# console program (students implement only TODO methods) Ctrl+C
using System; // Console
using System.Collections.Generic; // List<T>, IReadOnlyList<T>

namespace ItTechGenie.M1.GenericsDelegates.Q2
{
    public class Program
    {
        public static void Main()
        {
            var repo = new InMemoryRepository<Product>();    // repository for Product
            repo.Add(new Product(1, "Mouse", 699));          // add item
            repo.Add(new Product(2, "Keyboard", 1499));      // add item

            foreach (var p in repo.GetAll())                 // iterate all products
            {
                Console.WriteLine($"{p.Id} - {p.Name} - {p.Price}"); // print each product
            }
        }
    }

    public record Product(int Id, string Name, int Price);   // simple model

    public class InMemoryRepository<T>
    {
        private readonly List<T> _items = new();             // internal storage

        // ✅ TODO: Student must implement only this method
        public void Add(T item)
        {
            // TODO: Write your code here
            throw new NotImplementedException();             // remove after implementing
        }

        // ✅ TODO: Student must implement only this method
        public IReadOnlyList<T> GetAll()
        {
            // TODO: Write your code here
            throw new NotImplementedException();             // remove after implementing
        }
    }
}
3

Generic Constraint: Cache for Reference Types

Generics where T : class Dictionary Moderate

You are building a small cache for expensive objects loaded from an API (like product details). The cache must store **reference types only** (class types), because null values should be handled. ✅ Student task: - Implement Put and TryGet only. - Follow the method contracts and keep the dictionary usage safe.

Boilerplate C# console program (students implement only TODO methods) Ctrl+C
using System; // Console
using System.Collections.Generic; // Dictionary<K,V>

namespace ItTechGenie.M1.GenericsDelegates.Q3
{
    public class Program
    {
        public static void Main()
        {
            var cache = new SimpleCache<Product>();               // cache stores Product (class)
            cache.Put("P100", new Product("P100", "Pen"));        // add to cache

            if (cache.TryGet("P100", out var found))              // attempt read
            {
                Console.WriteLine($"Found: {found.Code} - {found.Name}"); // print
            }
        }
    }

    public class Product
    {
        public string Code { get; }                               // product code
        public string Name { get; }                               // product name

        public Product(string code, string name)
        {
            Code = code;                                          // assign
            Name = name;                                          // assign
        }
    }

    // Note: `where T : class` means only reference types are allowed here.
    public class SimpleCache<T> where T : class
    {
        private readonly Dictionary<string, T> _store = new();    // key-value store

        // ✅ TODO: Student must implement only this method
        public void Put(string key, T value)
        {
            // TODO: Write your code here
            throw new NotImplementedException();                  // remove after implementing
        }

        // ✅ TODO: Student must implement only this method
        public bool TryGet(string key, out T? value)
        {
            value = null;                                         // default output
            // TODO: Write your code here
            throw new NotImplementedException();                  // remove after implementing
        }
    }
}
4

Func<T,T,T>: Generic Calculator

Delegates Func Generics Moderate

A pricing engine wants to plug different operations (add, max, discount logic). Use **Func<T,T,T>** to represent the operation and apply it via a generic calculator. ✅ Student task: - Implement Apply<T>(T a, T b, Func<T,T,T> op) only. - Ensure null op throws ArgumentNullException.

Boilerplate C# console program (students implement only TODO methods) Ctrl+C
using System; // Console, ArgumentNullException

namespace ItTechGenie.M1.GenericsDelegates.Q4
{
    public class Program
    {
        public static void Main()
        {
            int sum = GenericCalculator.Apply(10, 20, (x, y) => x + y);        // addition
            Console.WriteLine($"Sum = {sum}");                                 // print

            decimal max = GenericCalculator.Apply(12.5m, 9.2m, (x, y) => x > y ? x : y); // max
            Console.WriteLine($"Max = {max}");                                 // print
        }
    }

    public static class GenericCalculator
    {
        // ✅ TODO: Student must implement only this method
        public static T Apply<T>(T a, T b, Func<T, T, T> op)
        {
            // TODO: Validate op is not null, then return op(a, b)
            throw new NotImplementedException(); // remove after implementing
        }
    }
}
5

Predicate<T>: Filter a List

Delegates Predicate Collections Moderate

A log-monitoring tool needs to filter events quickly. Use **Predicate<T>** to filter values from a list and return a new list. ✅ Student task: - Implement Filter<T>(IEnumerable<T> items, Predicate<T> predicate) only. - Validate arguments and return filtered results.

Boilerplate C# console program (students implement only TODO methods) Ctrl+C
using System; // Console
using System.Collections.Generic; // List<T>, IEnumerable<T>

namespace ItTechGenie.M1.GenericsDelegates.Q5
{
    public class Program
    {
        public static void Main()
        {
            var numbers = new List<int> { 5, 10, 15, 20, 25 };                // sample data
            var filtered = FilterUtil.Filter(numbers, n => n >= 15);          // keep >= 15

            foreach (var n in filtered)                                       // print result
            {
                Console.WriteLine(n);                                         // output each
            }
        }
    }

    public static class FilterUtil
    {
        // ✅ TODO: Student must implement only this method
        public static List<T> Filter<T>(IEnumerable<T> items, Predicate<T> predicate)
        {
            // TODO: Validate inputs, iterate items, apply predicate, build output list
            throw new NotImplementedException(); // remove after implementing
        }
    }
}
6

Multicast Delegate: Notification Pipeline

Delegates Multicast Error Handling Moderate

An order system must notify multiple channels (email, SMS, audit). Implement a multicast delegate pipeline so multiple handlers can be registered. ✅ Student task: - Implement Publish(string message) only. - Ensure one failing handler does NOT stop others (use try/catch per handler).

Boilerplate C# console program (students implement only TODO methods) Ctrl+C
using System; // Console

namespace ItTechGenie.M1.GenericsDelegates.Q6
{
    public delegate void Notify(string message); // delegate type for notifications

    public class Program
    {
        public static void Main()
        {
            var hub = new NotificationHub();                         // central hub

            hub.Register(EmailSender.Send);                          // add email handler
            hub.Register(SmsSender.Send);                            // add sms handler
            hub.Register(AuditLogger.Log);                           // add audit handler

            hub.Publish("Order #5001 placed successfully.");          // trigger notification
        }
    }

    public class NotificationHub
    {
        private Notify? _pipeline;                                   // multicast chain

        public void Register(Notify handler) => _pipeline += handler;   // add handler
        public void Unregister(Notify handler) => _pipeline -= handler; // remove handler

        // ✅ TODO: Student must implement only this method
        public void Publish(string message)
        {
            // TODO:
            // 1) If _pipeline is null, do nothing.
            // 2) Invoke each delegate safely so one exception doesn't break others.
            throw new NotImplementedException(); // remove after implementing
        }
    }

    public static class EmailSender
    {
        public static void Send(string message) => Console.WriteLine($"EMAIL: {message}"); // simulate email
    }

    public static class SmsSender
    {
        public static void Send(string message) => Console.WriteLine($"SMS  : {message}"); // simulate sms
    }

    public static class AuditLogger
    {
        public static void Log(string message) => Console.WriteLine($"AUDIT: {message}"); // simulate audit log
    }
}
7

where T : struct: Sum of Numeric Values

Generics where T : struct dynamic Moderate

A reporting job needs to sum numeric values without writing separate methods for int/decimal/double. Create a generic sum method for value types (struct). ✅ Student task: - Implement Sum<T>(IEnumerable<T> values) only. - Use the "safe dynamic pattern" described in the TODO comments.

Boilerplate C# console program (students implement only TODO methods) Ctrl+C
using System; // Console
using System.Collections.Generic; // List<T>, IEnumerable<T>

namespace ItTechGenie.M1.GenericsDelegates.Q7
{
    public class Program
    {
        public static void Main()
        {
            var ints = new List<int> { 1, 2, 3, 4 };                 // integer list
            Console.WriteLine(SumUtil.Sum(ints));                    // expected 10

            var decimals = new List<decimal> { 1.5m, 2.5m, 3.0m };    // decimal list
            Console.WriteLine(SumUtil.Sum(decimals));                // expected 7.0
        }
    }

    public static class SumUtil
    {
        // Note: This constraint allows only value types.
        public static T Sum<T>(IEnumerable<T> values) where T : struct
        {
            // ✅ TODO: Student must implement only this method
            // Hint (pattern):
            //   dynamic total = default(T);
            //   foreach (var v in values) total += (dynamic)v;
            //   return (T)total;
            throw new NotImplementedException(); // remove after implementing
        }
    }
}
8

Variance (in/out): Producer → Consumer Transfer

Generics Variance Delegates/Interfaces High

You are designing a message pipeline. - Producers create messages. - Consumers handle messages. Use **out** and **in** variance to allow safe assignment between base/derived types. ✅ Student task: - Implement Transfer<T>(IProducer<T> producer, IConsumer<T> consumer) only. - Transfer should: produce one item and send it to consumer.

Boilerplate C# console program (students implement only TODO methods) Ctrl+C
using System; // Console

namespace ItTechGenie.M1.GenericsDelegates.Q8
{
    // `out T` means Producer is covariant (can be used as base type producer).
    public interface IProducer<out T>
    {
        T Produce(); // produce an item
    }

    // `in T` means Consumer is contravariant (can consume derived items).
    public interface IConsumer<in T>
    {
        void Consume(T item); // consume an item
    }

    public class Program
    {
        public static void Main()
        {
            IProducer<EmailMessage> emailProducer = new EmailMessageProducer(); // produces EmailMessage
            IProducer<Message> messageProducer = emailProducer;                 // ✅ covariance works (EmailMessage -> Message)

            IConsumer<Message> messageConsumer = new MessageConsoleConsumer();  // consumes Message
            IConsumer<EmailMessage> emailConsumer = messageConsumer;            // ✅ contravariance works (Message consumer can consume EmailMessage)

            Pipeline.Transfer(messageProducer, emailConsumer);                  // transfer 1 item
        }
    }

    public static class Pipeline
    {
        // ✅ TODO: Student must implement only this method
        public static void Transfer<T>(IProducer<T> producer, IConsumer<T> consumer)
        {
            // TODO:
            // 1) produce item using producer.Produce()
            // 2) pass it to consumer.Consume(item)
            throw new NotImplementedException(); // remove after implementing
        }
    }

    public class Message
    {
        public string Text { get; }
        public Message(string text) => Text = text; // assign text
    }

    public class EmailMessage : Message
    {
        public string To { get; }
        public EmailMessage(string to, string text) : base(text) => To = to; // assign
    }

    public class EmailMessageProducer : IProducer<EmailMessage>
    {
        public EmailMessage Produce() => new EmailMessage("team@ittechgenie.com", "Welcome email"); // sample
    }

    public class MessageConsoleConsumer : IConsumer<Message>
    {
        public void Consume(Message item) => Console.WriteLine($"Consumed: {item.Text}"); // output
    }
}
9

Generic Event: Threshold Monitor (IComparable<T>)

Delegates event IComparable<T> High

A monitoring system checks values and raises an alert when a threshold is crossed. Make the monitor generic using **IComparable<T>** so it works for int/decimal/date etc. ✅ Student task: - Implement AddSample(T value) only. - If value >= threshold, raise the event with the value.

Boilerplate C# console program (students implement only TODO methods) Ctrl+C
using System; // Console

namespace ItTechGenie.M1.GenericsDelegates.Q9
{
    public class Program
    {
        public static void Main()
        {
            var monitor = new ThresholdMonitor<int>(threshold: 80);              // threshold 80

            monitor.ThresholdReached += v => Console.WriteLine($"ALERT: {v}");    // subscribe

            monitor.AddSample(60);                                               // no alert
            monitor.AddSample(90);                                               // should alert
        }
    }

    public class ThresholdMonitor<T> where T : IComparable<T>
    {
        private readonly T _threshold;                                           // threshold value
        public event Action<T>? ThresholdReached;                                // event callback

        public ThresholdMonitor(T threshold)
        {
            _threshold = threshold;                                              // store threshold
        }

        // ✅ TODO: Student must implement only this method
        public void AddSample(T value)
        {
            // TODO:
            // 1) Compare value with _threshold using CompareTo
            // 2) If value >= _threshold, invoke ThresholdReached (if not null)
            throw new NotImplementedException(); // remove after implementing
        }
    }
}
10

ExecuteWithRetry<T>: Generic Utility with Func<T>

Delegates Func<T> Exception Handling High

A service call sometimes fails (network issues). You want a reusable retry utility. ✅ Student task: - Implement ExecuteWithRetry<T>() only. - Retry up to maxAttempts. - Use shouldRetry(exception) to decide whether to retry. - If no more retries, rethrow the last exception.

Boilerplate C# console program (students implement only TODO methods) Ctrl+C
using System; // Console, Exception

namespace ItTechGenie.M1.GenericsDelegates.Q10
{
    public class Program
    {
        public static void Main()
        {
            int attempts = 0;                                                    // track attempts

            // A sample operation that fails twice, succeeds third time.
            int result = RetryUtil.ExecuteWithRetry(
                action: () =>
                {
                    attempts++;                                                  // increment
                    if (attempts < 3) throw new InvalidOperationException("Temporary failure"); // simulate failure
                    return 200;                                                  // success value
                },
                maxAttempts: 5,                                                  // max tries
                shouldRetry: ex => ex is InvalidOperationException                // retry only for this type
            );

            Console.WriteLine($"Result = {result}");                              // print
        }
    }

    public static class RetryUtil
    {
        // ✅ TODO: Student must implement only this method
        public static T ExecuteWithRetry<T>(Func<T> action, int maxAttempts, Func<Exception, bool> shouldRetry)
        {
            // TODO:
            // 1) Validate inputs (action, shouldRetry, maxAttempts >= 1)
            // 2) Loop attempts:
            //    - try: return action()
            //    - catch Exception ex:
            //        - if attempts reached OR shouldRetry(ex) is false => throw
            //        - else continue to next attempt
            throw new NotImplementedException(); // remove after implementing
        }
    }
}