Search code examples
c#.netgenericsparametersgeneric-method

Allow method to work with all inherited types


I have a class A from which B and C inherit. I also have lists of B and C like so: List<B> listB and List<C> listC.

I want to add elements to these lists but only after I do some logic. I have made a method that takes a list of any type and a related item to add.

public void AddItemToList<T>(List<T> item_list, T new_item)
{
    //do logic with properties of A...
}

I need to be able to use this method with both lists, like so:

AddItemToList<B>(listB, new B());
AddItemToList<C>(listC, new C());

However, since the type is generic, I cannot do the logic I want inside the method using A's properties.

If I use type A in the method, then I cannot pass the lists or items without casting them first.

Is there a way to set the type so I can pass matching parameters while still being able to do logic inside the method?


Solution

  • You can put a constrain on T, using where in method declaration

    See where (generic type constraint)

    using System;
    using System.Collections.Generic;
    
    class A
    {
        public int PropA;
    }
    
    class B : A
    {
    }
    
    class C : A
    {
    }
    
    class NotDerivedFromA
    {
    }
    
    class Foo
    {
        // where T:A force T to be A or a derived class
        public void AddItemToList<T>(List<T> item_list, T new_item) where T:A
        {
            Console.WriteLine(new_item.PropA);
        //do logic with properties of A...
        }
    }
    
    public class Program
    {
        public static void Main()
        {
            List<A> listA = new();
            List<B> listB = new();
            List<C> listC = new();
            
            Foo foo = new();
            
            foo.AddItemToList<A>(listA, new A());
            foo.AddItemToList<B>(listB, new B());
            foo.AddItemToList<C>(listC, new C());
            
            // this doen't compile:  NotDerivedFromA doesn't satisfy the constraint
            //foo.AddItemToList<NotDerivedFromA>(new List<NotDerivedFromA>(), new NotDerivedFromA());
            
            Console.WriteLine("Hello World");
        }
    }