我创建了一个接口和类,如下所示:
public interface IRecord
{
}
public class Person : IRecord
{
}
public class Company : IRecord
{
}
public class Contact : IRecord
{
}
public class Table<T> where T : IRecord
{
}
我还有一个静态类来管理表。我希望能够根据switch语句得到一个特定的表:
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;
}
}
但是,返回行都抛出编译错误:
Cannot implicitly convert type 'Table<Company>' to 'Table<IRecord>'
我可以修改我的代码以返回正确的表吗?
答案 0 :(得分:6)
您无法做到这一点,因为Table<Company>
不是Table<IRecord>
,即使Company
实现了IRecord
。这是因为Table<T>
不是covariant(类无论如何都不能协变,只有接口和代理可以)。
为了解释原因,我们假设您的Table<T>
班级有Insert(T record)
个方法;如果您能够将Table<Company>
视为Table<IRecord>
,则可以在表格中插入Person
或Contact
,这显然是不正确的。
现在,问题是,你怎么会使用返回的表呢?如果您只是要阅读它,您可以定义一个协变界面,如下所示:
public interface ITable<out T> where T : IRecord
{
}
然后让Table<T>
实现此界面,并将GetTable
更改为ITable<IRecord>
而不是Table<IRecord>
。
请注意,界面在输出位置只能有T
(例如,它可以使用T
作为参数的方法),或者它赢了& #39; t被允许是协变的。
答案 1 :(得分:3)
处理此问题的一种方法是添加非泛型基类。如果你想确保没有人可以尝试实例化它,它甚至可以是abstract
。
public abstract class TableBase
{
}
然后你可以:
public class Table<T> : TableBase where T : IRecord
{
}
现在这样可行:
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;
}