简体   繁体   中英

Function which can return any type of list

I am programming a function where a DataTable is given into and the function should recognize the type and convert the datatable to a list of its type. But my problem is that whenever i return the list i get an error:

Cannot implicitly convert type

'System.Collections.Generic.List<ADMPortal_2.Modles.ProductionPending>' 

to

'System.Collections.Generic.List<T>'

Now how is it possible to create a function which can return any type of list<> ?

eg

List<ProductionPending>
List<ProductionRecent>
List<MirrorDeployments>

Function

public List<T> ConvertToList<T>(DataTable dt, int listType)
    {

        if (listType == 1)
        {
            List<ProductionPending> list = new List<ProductionPending>();
            list = ConvertToProductionPending(dt);
            return list; 
        }
        else if (listType == 2)
        {
            List<ProductionRecent> list = new List<ProductionRecent>();
            ConvertToProductionRecent(dt);
            return list; 
        }
        else if (listType == 3)
        {
            List<MirrorDeployments> list = new List<MirrorDeployments>();
            list = ConvertToMirror(dt);
            return list; 
        }
        return list;
    }

Calling the function

The following code is the classic way of calling the function above.

        using (OracleConnection conn = new OracleConnection(cnnStr))
        {
            using (OracleCommand objCommand = new OracleCommand(strSql, conn))
            {
                objCommand.CommandType = CommandType.Text;
                DataTable dt = new DataTable();
                OracleDataAdapter adp = new OracleDataAdapter(objCommand);
                conn.Open();
                adp.Fill(dt);
                if (dt != null)
                {

                    list = ConvertToList<T>(dt, 1).ToList();
                }
            }
        }

The problem on your approach is that your types don´t have much in common. Only because of some class have some inheritance-relation doesn´t mean a list of that class has the same relation. In other words: a List<Derived> is not convertible to List<Base> .

You could achieve this if a List<T> was co-variant - which it is not for the following reason. Imagine a client of your ConvertToList -method does something like this:

var list = ConvertToList<MyBaseClass>(theTable, 1)

Now you could also do the following:

list.Add(new ProductionRecent());

which is probably not what you want. Thus you need some collection that is read-only , which means you can´t add instances to it. Therefor the IEnumerable<T> -interface is co-variant and can be used as return-type for your method.

IEnumerable is using out keyword in its generic type, so you can use derived types in return. So how about something like this:

        public static IEnumerable<IBase> ConvertToList(int listType)
    {

        if (listType == 1)
        {
            var list = new List<ClassA>();
            ...
            return list;
        }
        if (listType == 2)
        {
            var list = new List<ClassB>();
            ...
            return list;
        }
        if (listType == 3)
        {
            var list = new List<ClassC>();
            ...
            return list;
        }
        return null;
    }
}

public class ClassA : IBase
{ }
public class ClassB : IBase
{ }
public class ClassC : IBase
{ }
public interface IBase
{ }

More info here: Covariance and Contravariance in Generics

As you said they have a common base class:

public List<CommonBaseClass> ConvertToList(DataTable dt, int listType)
{
    var result = List<CommonBaseClass>();

    if (listType == 1)
    {
        result.AddRange(ConvertToProductionPending(dt));
    }
    else if (listType == 2)
    {
        result.AddRange(ConvertToProductionRecent(dt));
    }
    else if (listType == 3)
    {
        result.AddRange(ConvertToMirror(dt));
    }

    return result;
}

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