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.