如何处理类型不兼容的对象集合?

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 接口。