繁体   English   中英

C# 多级 Generics 具有继承/多态性

[英]C# Multi Level Generics with inheritance/polymorphism

我已经为此困惑了一段时间,但想知道是否可以通过另一种方法实现,或者我只是错过了一步。

这是基类。

public class StartType0<T1, T2>
    where T1 : StartType1
    where T2 : StartType2
{}

public class StartType1 {}

public class StartType2 {}

public class EndType0 : StartType0<EndType1, EndType2> {}

public class EndType1 : StartType1 {}

public class EndType2 : StartType2 {}

我想创建一个持有人/容器 class 来保存我的 EndType0 class 的数组,它将在 Unity 中用于为我的 StartType0 class 绘制一个通用自定义属性抽屉。

任何正确方向的建议或指示都会很棒,因为在过去的几个月里我已经多次尝试解决这个问题。

我想我可以尝试提供每个参数,但我无法将 StartType0 转换为我的 EndType0。

public class TypeContainer<T0, T1, T2>
    where T0 : StartType0<T1, T2>
    where T1 : StartType1
    where T2 : StartType2
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<StartType0<EndType1, EndType2>, EndType1, EndType2> container = new TypeContainer<StartType0<EndType1, EndType2>, EndType1, EndType2>();

    public Tester()
    {
        EndType0 instance = (EndType0)container.array[0];
    }
}

我想我可以尝试为 StartType0 参数提供 EndType0,但我猜它有问题,因为没有考虑多态性。

public class TypeContainer<T0, T1, T2>
    where T0 : StartType0<T1, T2>
    where T1 : StartType1
    where T2 : StartType2
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<EndType0, EndType1, EndType2> container = new TypeContainer<EndType0, EndType1, EndType2>();

    public Tester()
    {
        EndType0 instance = container.array[0];
    }
}

理想情况下,我会喜欢以这种方式处理它,并涉及一些美味的多态性。

public class TypeContainer<T>
    where T : StartType0<StartType1, StartType2>
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<EndType0> container = new TypeContainer<EndType0>();

    public Tester()
    {
        EndType0 instance = container.array[0];
    }
}

-编辑1-

在关注@JohnathanBarclay 的评论后,我设法做出以下决定。

public class StartType0<out T1, out T2>
    where T1 : StartType1, IStartType1
    where T2 : StartType2, IStartType2
{}

public interface IStartType1 {}

public class StartType1 : IStartType1 {}

public interface IStartType2 {}

public class StartType2 : IStartType2 {}

public class EndType0 : StartType0<EndType1, EndType2> {}

public class EndType1 : StartType1 {}

public class EndType2 : StartType2 {}

然后允许我执行以下操作并完成编译。

public class TypeContainer<T0, T1, T2>
    where T0 : IStartType0<T1, T2>
    where T1 : IStartType1
    where T2 : IStartType2
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<EndType0, EndType1, EndType2> container = new TypeContainer<EndType0, EndType1, EndType2>();

    public Tester()
    {
        EndType0 instance = container.array[0];
    }
}

不过,这在统一编辑器中存在问题。

-编辑2-

经过一番尝试后,我找到了目前最理想的设置

public interface IStartType0<out T1, out T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{}

public class StartType0<T1, T2>
    IStartType0<T1, T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{}

public interface IStartType1<out T> where T StartType1 {}

public class StartType1 : IStartType1<StartType1> {}

public interface IStartType2<out T> where T StartType2 {}

public class StartType2 : IStartType2<StartType2> {}

public class EndType0 : StartType0<EndType1, EndType2> {}

public class EndType1 : StartType1 {}

public class EndType2 : StartType2 {}

public class TypeContainer<T0, T1, T2>
    where T0 : IStartType0<T1, T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<EndType0, EndType1, EndType2> container = new TypeContainer<EndType0, EndType1, EndType2>();

    public Tester()
    {
        EndType0 instance = container.array[0];
    }
}

有了“或多或少”有保证的基本类型,我就可以在这些基础类型上运行我的 CustomPropertyDrawer 并生成自定义检查器,甚至可以利用“Activator”来处理通用类型。

在 generics 中尝试了一些变化之后,我发现目前为止我的理想设置

public interface IStartType0<out T1, out T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{}

public class StartType0<T1, T2>
    IStartType0<T1, T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{}

public interface IStartType1<out T> where T StartType1 {}

public class StartType1 : IStartType1<StartType1> {}

public interface IStartType2<out T> where T StartType2 {}

public class StartType2 : IStartType2<StartType2> {}

public class EndType0 : StartType0<EndType1, EndType2> {}

public class EndType1 : StartType1 {}

public class EndType2 : StartType2 {}

public class TypeContainer<T0, T1, T2>
    where T0 : IStartType0<T1, T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<EndType0, EndType1, EndType2> container = new TypeContainer<EndType0, EndType1, EndType2>();

    public Tester()
    {
        EndType0 instance = container.array[0];
    }
}

有了“或多或少”有保证的基本类型,我就可以在这些基础类型上运行我的 CustomPropertyDrawer 并生成自定义检查器,甚至可以利用“Activator”来处理通用类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM