【问题标题】:c# generic inheritance base class to child classc#泛型继承基类到子类
【发布时间】:2017-01-05 12:50:03
【问题描述】:

我有以下基类:

public abstract class BaseClass<T>  where T : IComparable
{

}

还有这个子类:

public class ChildClass<T> : BaseClass<int>
{

}

从程序的不同位置我有以下代码:

  List<BaseClass<IComparable>> objectList= new List<BaseClass<IComparable>>();
  ChildClass<int> childObject= new ChildClass<int>();
  ChildClass<double> childObject2= new ChildClass<double>()
  //both int and double are IComparable


//the bellow code dosent compile, it syas it cannot be casted, i dont understand why becuse they are his child class:
  objectList.Add(childObject);
  objectList.Add(childObject2); 

【问题讨论】:

  • 你想要的是covariance,它在类中不可用,但在接口中可用。但是,如果泛型类型仅用作属性(只读)和方法(返回类型,但不是参数)的输出,则只能使泛型类型协变。另一种选择是只使泛型类型匹配。
  • 首先,尝试编码BaseClass&lt;IComparable&gt; item = new ChildClass&lt;int&gt;();,然后找到解决方案,然后将解决方案移植到您的列表方案(我评论中的代码示例不起作用,但这基本上是您尝试执行的操作致电Add)
  • @grek40 BaseClass&lt;IComparable&gt; item = new ChildClass&lt;int&gt;(); 不起作用,原因与列表相同。
  • @Carson 是的,它基本上是一个提示如何将手头的问题简化为最小形式(MCVE *hint*)

标签: c# oop generics inheritance


【解决方案1】:

我不确定您需要该列表的用途,但正如 juharr 在您的 cmets 中所说,这是 covariance 的问题。如果您绝对需要找到一种通用的方法来根据列表中的某种值或某组值来获取子类,您仍然可以这样做。虽然,它有点绕圈子,也许不是最好的解决方案......

类似这样的:

private void Main()
{
    var values = new List<IComparable>();

    values.Add(10);
    values.Add(5.55D);

    foreach (var value in values) {
        Console.WriteLine(value); // The value
        var childClass = BuildChild(value);
        Console.WriteLine(childClass.GetType().FullName); // The type
        // Using dynamic will work
        ((dynamic)childClass).DoWork((dynamic)value);
    }
}

private static object BuildChild(IComparable value)
{
    if (value == null)
        throw new ArgumentNullException(nameof(value));

    Type valueType = value.GetType();
    Type childClassType = typeof(ChildClass<>).MakeGenericType(valueType);
    return Activator.CreateInstance(childClassType);
}

// Define other methods and classes here
public abstract class BaseClass<T> where T : IComparable
{
}

public class ChildClass<T> : BaseClass<T> where T : IComparable
{
    public void DoWork(T value) {
        Console.WriteLine(value.GetType().FullName);
    }
}

请注意,由于您使用反射来解析类型,因此此方法比使用预实例化实例时要慢一点。我不确定您在反射和动态调用方面的经验如何,所以这只是一个提醒!

就像我说的,我不知道你需要这个做什么......或者为什么你需要列表中的特定子类。这个解决方案是另一种方式,您可以通过在运行时和动态生成所需的类来获得类似的功能。

另一种选择是删除基类上的泛型约束并使用反射来解析子类,或者只是一起删除泛型约束并可能通过方法级泛型解析类型。但是,不知道您需要什么使我无法帮助您找到最佳解决方案,所以这些只是想法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多