Home > Software engineering >  Pass List<DerivedClass> to method expecting List<ParentClass> in C#
Pass List<DerivedClass> to method expecting List<ParentClass> in C#

Time:01-05

I'm creating an app that returns a list of metals to use in various conditions. I have a Metal class then classes for each type of Metal like Steel, Aluminum, etc. If I have a list of different Steels, I want to first select the best ones based on a set of properties common to all Metals then do a second pass based on the unique properties of Steel. (This isn't my exact problem but my problem is analogous.)

I can't figure out how to pass a List<Steel> to the GetBest() method of the Metal class as shown below that takes its first argument of type List<Metal>. The code won't compile due to error at the line highlighted below with **: "Argument 1: cannot convert from 'System.Collections.Generic.List<Steel>' to 'System.Collections.Generic.List<Metal>'.

public class Metal {

    public int PropA { get; set; }

    public List<Metal> GetBest( List<Metal> list, int condition1 )
    {
        var best = new List<Metal>();

      //Analysis code here...

        return best;
    }
}

public class Steel : Metal
{
    public int PropB { get; set; }

    public List<Steel> GetBest(List<Steel> list, int condition1, int condition2 ) {

        var bestSteel = new List<Steel>();

      //Do first pass selection based on properties of all metals.
        **bestSteel = Metal.GetBest(list, condition1);**

      //Do some additional analysis based to Steel's unique properties.
      //Analysis code here...

        return bestSteel;

    }

CodePudding user response:

You could use a constrained generic method:

public static List<T> GetBest<T>(List<T> list, int condition1) where T : Metal
{
    var best = new List<T>();

    // Analysis code here...

    return best;
}

CodePudding user response:

I'm going to answer a different question! A look at how I might approach this problem without confounding my objects (Metal, Steel) with my logic for picking the best metal based on some conditions:

public class Metal{}
public class Steel:Metal{}

public class MetalPickerContext
{
    public int Condition1{ get;set;}
}

public class MetalPicker<TMetal, TContext> 
    where TMetal: Metal
    where TContext: MetalPickerContext
{
    public virtual IEnumerable<TMetal> GetBest(IEnumerable<TMetal> list, TContext context)
    {
        var result = new List<TMetal>();
        // logic for picking the best metal based on Condition1
        
        return result;
    }
}

public class SteelPickerContext: MetalPickerContext
{
    public int Condition2{get;set;}
}

public class SteelPicker : MetalPicker<Steel,SteelPickerContext>
{
    public override IEnumerable<Steel> GetBest(IEnumerable<Steel> list, SteelPickerContext context)
    {
        var initialResult = base.GetBest(list,context);
        // Having called the base logic apply more with reference to Condition2
        return initialResult;
    }
}

This compiles (as you can see here) and I could expand the example a bit given some more details to make it a working one. Let me know if that would help you.

  •  Tags:  
  • Related