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?
CodePudding user response:
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");
}
}
CodePudding user response:
If your generic method needs to perform type-specific functions, then it isn't generic. However, you could take a functional approach and pass in an Action<T>
delegate that does the type-specific work:
public void AddItemToList<T>(List<T> item_list, T new_item, Action<T> effect)
{
effect(new_item);
// etc
}
then call it:
// `x` below is inferred to be of type `int`
AddItemToList(new List<int>(), 0 ,x => Console.WriteLine(x 1));