Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving generic method parameters in C#

Tags:

c#

wsdl

I have a method that is overloaded 3 times with the exact same functionality, the only change is one parameter which is a list of a concrete type.

private void _doWork(string name, List<TargetItem> members)
{
    foreach(var member in members)
    {
      _doExtraWork(member.TimeToWork);
    }
}

private void _doWork(string name, List<NonTargetItem> members)
{
    foreach(var member in members)
    {
      _doExtraWork(member.TimeToWork);
    }
}

Thing to know here is the 2 classes in the lists are coming from a WSDL definition. The operation in the iteration is on shared members as they derive from the same base class, however this inheritance is abstracted in the WSDL.

I have tried to do something like this -

private void _doWork<T>(string name, List<T> members)
{
    var commonList = new List<>(); /// what type should I use here?

    if(typeof (T) == typeof(TargetItem))
    {
      commonList = members; // assume equal to means copying members to commonList with type conversion
    }
    if(typeof (T) == typeof(NonTargetItem))
    {
      commonList = members;
    }
    foreach(var member in commonList)
    {
      _doExtraWork(member.TimeToWork);
    }
}

Is this the right way to approach the problem and refactor this common code, or am I missing something here?

like image 800
lolcat Avatar asked Aug 03 '26 05:08

lolcat


1 Answers

you can do something like this

 private static void _doWork<T>(string name, T members) where T : IEnumerable
{
     foreach(var member in members)
    {
      _doExtraWork(member.TimeToWork);
    }
}

In your Calling Code

_doWork("sdfsd", new List<TargetItem>()); // here just as example I am passing new instance
_doWork("sdfsd", new List<NonTargetItem>()); // here just as example I am passing new instance

As the List<T> is of type IEnumerable<T> which in turn is of type IEnumerable. You can add IEnumerable generic constaints in your generic functions. In this way, you do not have to do type checking in your generic functions.

If you want to implement single doExtraWork method then you need to have CommonType for both TargetItem and NonTargetItem. you can solve this using Adapter Pattern like below

Interface IItem
{
 int TimeToWorkAdapt {get;}
}

//Now create a wrapper class for TargetItem and NonTargetItem

Class TargetItemAdapt : TargetItem,IItem
{
   public int TimeToWorkAdapt 
       {
           get { base.TimeToWork;}    
       }
}

Class NonTargetItemAdapt : NonTargetItem,IItem
{
   public int TimeToWorkAdapt 
       {
           get { base.TimeToWork;}    
       }
}
 // write a generic function which wrap calls to your do extra work method but with generic constriants to interface
private static void _doExtraWork<T>(T members) where T : IItem
    {
          _doExtraWork(member.TimeToWorkAdapt);

    }
// In your Main program...now use our wrapper classes

_doWork("sdfsd", new List<TargetItemAdapt>()); // here just as example I am passing new instance
_doWork("sdfsd", new List<NonTargetItemAdapt>()); // here just as example I am passing new instance
like image 83
Viru Avatar answered Aug 05 '26 19:08

Viru



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!