简体   繁体   中英

Creating one helper method for different types via interface c#

I have a requirement to order several lists by the same value. But, for whatever reason, these lists contain objects of different types which share this value. Let's call it ChildID .

The simplified model code would look something like this:

public class Child
{
    public string ChildID { get; set; }
}

public class Parent
{
    public Child Child { get; set; }
}

public class OtherClassID 
{ 
    public int ID { get; set; }
    public string ChildID { get; set; }
}

public class SomeOtherClass
{
    public OtherClassID ID { get; set; }
}

So, in order to avoid code duplication, I tried this:

public interface IHasChildID
{
    string GetChildID();
}

public class Child : IHasChildID
{
    public string ChildID { get; set; }
    public string GetChildID()
    {
        return ChildID;
    }
}

public class Parent : IHasChildID
{
    public Child Child { get; set; }
    public string GetChildID()
    {
        return Child.ChildID;
    }
}

public class OtherClassID 
{ 
    public int ID { get; set; }
    public string ChildID { get; set; }
}

public class SomeOtherClass : IHasChildID
{
    public OtherClassID ID { get; set; }
    public string GetChildID()
    {
        return ID.ChildID;
    }
}

And when I created a helper class with a helper method which takes an interface as a parameter, I expected it to work:

public static class ChildOrderHelper
{
    public static IEnumerable<IHasChildID> OrderChildren(IEnumerable<IHasChildID> children)
    {
        var childrenList = children.ToList();
        //do some splitting, ordering and conatenation of lists
        return orderedList;

    }
}

But, on every helper call I get an error:

List<Child> originalList = GetChildren(); // whatever
// some lines of code
var orderedList = ChildOrderHelper.OrderChildren(originalList).ToList(); // error

Error CS1503 Argument 1: cannot convert from 'System.Collections.Generic.List<NamespaceOne.Child>' to 'System.Collections.Generic.List<NamespaceTwo.IHasChildID>'

And so for every helper call, no matter the type.

One thing to note is that I've given an example with three distinct types that have this value and need to be ordered by it. In the project, there is probably 10 or more.

I guess there is something fundamental I don't yet understand about interface usage, but any help would be appreciated on this matter.

I'm not entirely sure what your overall use case is, but maybe it would be beneficial to make the OrderChildren method generic, as follows:

public static class ChildOrderHelper
{
  public static IEnumerable<T> OrderChildren<T>(IEnumerable<T> children) where T : IHasChildID
  {
    var childrenList = children.ToList();
    //just a simple example of what I'm guessing the method could do...
    return childrenList.OrderBy(c => c.GetChildID()).ToList();
  }
}

And call it as follows:

List<Child> originalList = GetChildren();
List<Child> orderedList = ChildOrderHelper.OrderChildren<Child>(originalList).ToList();

The approach can be taken like defining an interface and then implemenint that one in all the required classes or a base class that can lookup the child id.

Below is a sample of the source code.

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections;

public class Program
{
    public static void Main()
    {
        var parents = new List<Parent>();
        parents.Add(new Parent{ChildId = "123"});
        parents.Add(new Parent{ChildId = "321"});
        parents.Add(new Parent{ChildId = "456"});

        var result = ChildHelpers.OrderChildren(parents);

        foreach(var res in result) {
            Console.WriteLine(res.ChildId);
        }
        Console.WriteLine("Hello World");
    }
}

public interface IChild {
    string ChildId {get;set;}
}

public class Child : IChild {
    public string Name {get;set;}
    public string ChildId {get;set;}
}

public class Parent : IChild {
    public Parent() {
        child = new Child();
    }
    public Child child {get;set;}
    public string ChildId {
        get{
            return child.ChildId;
        }
        set{
            child.ChildId = value;
        }
    }
}

public class AnotherChild : IChild {
    public string Description{get;set;}
    public string ChildId {get;set;}
}

public static class ChildHelpers {
    public static IEnumerable<IChild> OrderChildren(IEnumerable<IChild> children)
    {
        return children.OrderBy(c=>c.ChildId).AsEnumerable();
    }
}

If you would like to playaround with this sample and see other options if required, please refer this link.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM