需要将泛型转换为其接口
本文关键字:接口 转换 泛型 | 更新日期: 2023-09-27 18:21:30
我创建了一个接口和类,如下所示:
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>'
我可以修改我的代码以返回正确的表吗?
您不能这样做,因为Table<Company>
不是Table<IRecord>
,即使Company
实现了IRecord
。这是因为Table<T>
不是协变的(类无论如何都不能是协变的,只有接口和委托可以)。
为了解释原因,让我们假设您的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
作为参数的方法),或者它不允许是协变的。
处理此问题的一种方法是添加一个非泛型基类。如果你想确保没有人可以尝试实例化它,它甚至可以是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;
}