You need to convert the common interface to its interface

I created an interface and classes like this:

public interface IRecord
{
}
public class Person : IRecord
{
}
public class Company : IRecord
{
}
public class Contact : IRecord
{
}
public class Table<T> where T : IRecord
{
}

      

I also have a static class for managing tables. I would like to get a specific table based on a switch statement:

public class DataBase
{
    public static Table<Person> Persons { get; set; }
    public static Table<Contact> Contacts { get; set; }
    public static Table<Company> Companies { get; set; }

    public static Table<IRecord> GetTable(eDataType type)
    {
        switch (type)
        {
            case eDataType.company:
                return Companies;
            case eDataType.contact:
                return Contacts;
            case eDataType.person:
                return Persons;
        }
        return null;
    }
}

      

However, return lines all throw compilation errors:

Cannot implicitly convert type 'Table<Company>' to 'Table<IRecord>'

      

Can I change my code to return the correct table?

+3


source to share


2 answers


One way to deal with this is to add a non-generic base class. It might even be abstract

if you want no one to try and instantiate it.

public abstract class TableBase 
{
}

      

And then you can:



public class Table<T> : TableBase where T : IRecord
{
}

      

And now this will work:

public static TableBase GetTable(eDataType type)
{
    switch (type)
    {
        case eDataType.company:
            return Companies;
        case eDataType.contact:
            return Contacts;
        case eDataType.person:
            return Persons;
    }
    return null;
}

      

+3


source


You can not do that, because Table<Company>

is not Table<IRecord>

, though Company

implements IRecord

. This is because it is Table<T>

not covariant (classes cannot be covariant anyway, only interfaces and delegates can).

To explain, let's say your class Table<T>

has a method Insert(T record)

; if you could see Table<Company>

how Table<IRecord>

, it would allow you to insert into the table, Person

or Contact

which would obviously be wrong.

Now, the question is, how are you going to use the returned table anyway? If you're just reading this, you can define a covariant interface like this:



public interface ITable<out T> where T : IRecord
{
}

      

Then make Table<T>

implement this interface and change GetTable

to return ITable<IRecord>

instead Table<IRecord>

.

Note that an interface can only have an T

output position (i.e. it cannot, for example, have a method that takes T

as a parameter), or it will not be allowed to be covariant.

+6


source







All Articles