0

I am still trying to fully understand generics especially when used in conjunction with base classes. I have a generic table class that takes in a derived type of a row class but is constrained to be a base row. Since the base table class is constraint to taking a type base row how can I pass this class with any derived class to be of base row type.

public interface Itable<in TRow>  where TRow : row{
    //*This will not compile with the list of TRow should it be List<row>? If so how do i force that conversion?
    List<TRow> IfindLst();
}
public abstract class table<TRow> where TRow : row, Itable<row>
{
    //*This is the list of rows i want to be able to send as their base row 
    public List<TRow> derivedRowLst = new List<TRow>();
    public table()
    {

    }
    public List<row> IfindLst()
   {
       return derivedRowLst;
   }
}
//Derive instance of base table class
public class tableInstOne : table<rowInstOne>
{

}
//Base class for row that all derived rows are guarantee to be of
public abstract class row
{

}
public class rowInstOne : row
{
    public rowInstOne() { }
}
public class tester
{
    public static void main()
    {
        Itable<row> tblInstOne = new tableInstOne();
        //*This is what I am trying to figure out how to do get this list of base row class from the base table class. Even though it is stored as List<TRow> or derived row class. 
        List<row> baseLst = tblInstOne.IfindLst();
    }

}

This does not allow me to send the instantiated table class as having its base guaranteed type. I used to not have the table class as generic and so all rows were just used as base row but this required downcasting at other points in code that I am trying to avoid. Now I don't have to downcast BUT I cannot send this table class with base as a parameter to classes that don't care about the derived row type and only need to utilize the base row functions. Thanks for any help!

user3284717
  • 35
  • 1
  • 6
  • 1
    You can either change `AcceptDerviedRowTypeAsBase` to be generic, or create a generic interface for rows where the type parameter is specified as covariant – Chris Yungmann Oct 17 '19 at 16:22
  • Thanks. I did get it to compile if i make AcceptDerivedRowTypeAsBase to be generic like you said but I have a situation where I need to get the table within a button click like: table thsTable> = (new full_record_id(fullTag.fullID)).ToIOItem().AsTable(); so i'm assuming i will want to use an interface instead so i can pass it here. How would I create that interface to have all the base methods of table available? Thanks again. I read a few other similar answers about it but still am unclear how I would need to make the interface to make it work in this situation. – user3284717 Oct 17 '19 at 17:20
  • 1
    could you perhaps create a new question or update your question to reflect your current issue and steps you have tried? – Chris Yungmann Oct 18 '19 at 14:59
  • Thanks Chris. Let me be a little more specific. I added my attempt at making this work above with an interface. The problem i am having is using a List with as a list of its base row class. I would like the interface to see the list of derived row as just a list of its base class. – user3284717 Oct 19 '19 at 14:38

1 Answers1

0

It is hard to tell exactly what you are trying to accomplish. Perhaps the following code will help. Note that the method IfindLst returns a List<TRow> rather than a List<Row>, which I think may be part of your problem.

public abstract class Table<TRow> where TRow : Row
{
    //*This is the list of rows i want to be able to send as their base row 
    public List<TRow> derivedRowLst = new List<TRow>();
    public Table()
    {

    }
    public List<TRow> IfindLst()
    {
       return derivedRowLst;
    }
}
//Derive instance of base table class
public class TableInstOne : Table<RowInstOne>
{

}
//Base class for row that all derived rows are guarantee to be of
public abstract class Row
{

}
public class RowInstOne : Row
{
    public RowInstOne() { }
}

public static class Program
{
    public static void Main(string[] args)
    {
        Table<RowInstOne> tblInstOne = new TableInstOne();
        //*This is what I am trying to figure out how to do get this list of base row class from the base table class. Even though it is stored as List<TRow> or derived row class. 
        List<Row> baseLst = tblInstOne.IfindLst().OfType<Row>().ToList();
        List<Row> baseLst2 = tblInstOne.IfindLst().ConvertAll(x => (Row)x);
        List<Row> baseLst3 = tblInstOne.IfindLst().Cast<Row>().ToList();
        IEnumerable<Row> baseLst3 = tblInstOne.IfindLst();
    }
}

Note on the last line I demonstrate the use of the covariant IEnumerable<T> interface to avoid any casting or runtime type-checking.

Chris Yungmann
  • 1,079
  • 6
  • 14