c#泛型基类方法返回派生类的类型

标签 c# generics

我想要一个基类方法返回派生类的类型。 根据 Can a Base Class Method return the type of the derived class?

基类

public class BaseClass<T>
{
}

扩展

public static class ExtensionMethods
{
   public static U Project<U, T>(this U node)
     where U : BaseClass<T>
  {
     // do something
     return node;
  }
}

子类

public class ChildClass: BaseClass<string>
{
}

用法

var child= new ChildClass();
var projected = child.Project(); // error: can't infer type T
var projected = child.Project<ChildClass, string>(); // ok

问题: 一种解决方案是 How to return a derived class using only code in the base class? ,但是从子类继承的类将不起作用。 如何在不指定 T 的情况下使用方法?

最佳答案

答案是您需要提供所有管道以手动克隆对象,并让编译器决定正确的重载。

public interface ICSGNode<T> where T:ICSGNode<T>
{
    T Clone();
    void Invert();
}
public class NodeList<T> : Collection<T>
    where T : ICSGNode<T> 

{
    public NodeList(params T[] items) : base(items) { }
    public static implicit operator NodeList<T>(T[] array) { return new NodeList<T>(array); }

    public T[] Clone() { return this.Select((n) => n.Clone()).ToArray(); }
}

public class PolygonNode : ICSGNode<PolygonNode>, ICloneable
{
    public PolygonNode()
    {
        // create a unique object
    }
    public PolygonNode(PolygonNode other)
    {
        // create a copy
    }

    public void Invert()
    {
        throw new NotImplementedException();
    }
    public PolygonNode Clone() { return new PolygonNode(this); }
    object ICloneable.Clone() { return Clone(); }

}

public class PolygonList : NodeList<PolygonNode>, ICloneable
{
    public PolygonList(params PolygonNode[] items) : base(items) { }
    public static implicit operator PolygonList(PolygonNode[] array) { return new PolygonList(array); }

    public new PolygonList Clone() { return new PolygonList(base.Clone()); }
    object ICloneable.Clone() { return Clone(); }
}
class Program
{
    static void Main(string[] args)
    {
        var list = new PolygonList
        {
            new PolygonNode(),
            new PolygonNode(),
            new PolygonNode(),
        };
        var clone = list.Clone();
        // clone is of `PolygonList` type
    }
}

使用的技巧:

  • 仅将ICloneable 接口(interface)应用于派生类。
  • 用强类型的 Clone() 方法覆盖返回 object 的默认行为。
  • 实现仅在构造函数内复制对象属性的复制构造函数。
  • 最后,避免从任何基本 Clone() 方法返回具体或通用集合类型。返回一个数组,并让派生类从项目数组中组装强类型克隆。

关于c#泛型基类方法返回派生类的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48313356/

相关文章:

c# - 比较 2 List<Dictionary<string, object>>

c# - Selenium 3.8.0 wait.until 调用抛出异常

java - java泛型绑定(bind)不匹配错误

ios - 我想要一个用于核心数据的通用 fetchedResultsController 来支持多个模型

c# - 为什么字符串的功能不同

c# - 如何将鼠标移动位置值存储在数组中?

c# - 在 C# 中是否有从 int 类型安全的枚举转换?

java - 如何在 Java 中使用泛型来使用两个接口(interface)作为参数?

java - java中给定键随机访问映射条目

java - HashMap 与 ArrayList 中类型参数的实现