簡體   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