如何处理类型不兼容的对象集合?
How to work with a collection of objects with an incompatible type?
我有一个 table 控制器,用于多个 table(数据模型)。这是它的简化版本:
public abstract class TableBase
{
public virtual void TableName()
{
Console.WriteLine("I am Table: " + this.GetType().Name);
}
}
public class TableA : TableBase
{
}
public class TableB : TableBase
{
}
public class TableC : TableBase
{
}
public class Controller<T> where T : TableBase
{
public Controller(T table)
{
table.TableName();
}
public void Synchronize();
}
那我基本是这样用的:
Controller<TableA> Controller1 = new Controller<TableA>(new TableA());
Controller<TableB> Controller2 = new Controller<TableB>(new TableB());
Controller<TableC> Controller3 = new Controller<TableC>(new TableC());
一切都很容易,但当我想将控制器添加到控制器列表时,问题就来了:
List<Controller<TableBase>> ControllerList = new List<Controller<TableBase>>();
ControllerList.Add(Controller1);
ControllerList.Add(Controller2);
ControllerList.Add(Controller3);
它告诉我无法将 Table(A,B,C) 转换为 TableBase 的类型,出于某种原因在控制器中使用 base 作为类型 class 吓坏了一切。我不认为这会导致差异问题,但它似乎是。我只想在每个控制器上循环调用 Synchronize()
。我如何让它工作?
如果您需要在不兼容的类型中调用通用方法,您可以定义一个接口来公开您需要调用的功能。
在此代码示例中,我添加了一个新接口 ICanSync
,其方法签名与您的 Controller<T>
匹配 Synchronize()
,并修改了 Controller<T>
以实现新接口.这意味着您可以创建 List<ICanSync>
并添加具有不兼容泛型类型的控制器。
// new interface to use
public interface ICanSync
{
void Synchronize();
}
public abstract class TableBase
{
public virtual void TableName()
{
Console.WriteLine("I am Table: " + this.GetType().Name);
}
}
public class TableA : TableBase
{
}
public class TableB : TableBase
{
}
public class TableC : TableBase
{
}
public class Controller<T> : ICanSync where T : TableBase
{
private TableBase _t;
public Controller(T table)
{
_t = table;
}
public void Synchronize()
{
_t.TableName();
}
}
您可以声明一个 List<ICanSync>
并对它们全部调用 Synchronize()
。
Controller<TableA> Controller1 = new Controller<TableA>(new TableA());
Controller<TableB> Controller2 = new Controller<TableB>(new TableB());
Controller<TableC> Controller3 = new Controller<TableC>(new TableC());
List<ICanSync> ControllerList = new List<ICanSync> {Controller1, Controller2, Controller3};
foreach (var controller in ControllerList)
{
controller.Synchronize();
}
这是类型安全的,因为 ICanSync
与它自身的实例自然兼容。如果您需要使用 T
的更丰富的通用功能,您可以声明一个 covariant or contravariant 接口。
我有一个 table 控制器,用于多个 table(数据模型)。这是它的简化版本:
public abstract class TableBase
{
public virtual void TableName()
{
Console.WriteLine("I am Table: " + this.GetType().Name);
}
}
public class TableA : TableBase
{
}
public class TableB : TableBase
{
}
public class TableC : TableBase
{
}
public class Controller<T> where T : TableBase
{
public Controller(T table)
{
table.TableName();
}
public void Synchronize();
}
那我基本是这样用的:
Controller<TableA> Controller1 = new Controller<TableA>(new TableA());
Controller<TableB> Controller2 = new Controller<TableB>(new TableB());
Controller<TableC> Controller3 = new Controller<TableC>(new TableC());
一切都很容易,但当我想将控制器添加到控制器列表时,问题就来了:
List<Controller<TableBase>> ControllerList = new List<Controller<TableBase>>();
ControllerList.Add(Controller1);
ControllerList.Add(Controller2);
ControllerList.Add(Controller3);
它告诉我无法将 Table(A,B,C) 转换为 TableBase 的类型,出于某种原因在控制器中使用 base 作为类型 class 吓坏了一切。我不认为这会导致差异问题,但它似乎是。我只想在每个控制器上循环调用 Synchronize()
。我如何让它工作?
如果您需要在不兼容的类型中调用通用方法,您可以定义一个接口来公开您需要调用的功能。
在此代码示例中,我添加了一个新接口 ICanSync
,其方法签名与您的 Controller<T>
匹配 Synchronize()
,并修改了 Controller<T>
以实现新接口.这意味着您可以创建 List<ICanSync>
并添加具有不兼容泛型类型的控制器。
// new interface to use
public interface ICanSync
{
void Synchronize();
}
public abstract class TableBase
{
public virtual void TableName()
{
Console.WriteLine("I am Table: " + this.GetType().Name);
}
}
public class TableA : TableBase
{
}
public class TableB : TableBase
{
}
public class TableC : TableBase
{
}
public class Controller<T> : ICanSync where T : TableBase
{
private TableBase _t;
public Controller(T table)
{
_t = table;
}
public void Synchronize()
{
_t.TableName();
}
}
您可以声明一个 List<ICanSync>
并对它们全部调用 Synchronize()
。
Controller<TableA> Controller1 = new Controller<TableA>(new TableA());
Controller<TableB> Controller2 = new Controller<TableB>(new TableB());
Controller<TableC> Controller3 = new Controller<TableC>(new TableC());
List<ICanSync> ControllerList = new List<ICanSync> {Controller1, Controller2, Controller3};
foreach (var controller in ControllerList)
{
controller.Synchronize();
}
这是类型安全的,因为 ICanSync
与它自身的实例自然兼容。如果您需要使用 T
的更丰富的通用功能,您可以声明一个 covariant or contravariant 接口。