簡體   English   中英

使用非泛型類中的泛型

[英]Using generics from non-generic class

我對泛型有疑問。 我寫了一個通用類。 我從該課程中派生其他課程。

最后,我想在另一個類中使用此派生類,但是我沒有找到有效的解決方案來使它正常工作。

這是我的簡化示例:

// Generic base class
public class Information<T>
{
    public T StatusCode;
    public bool Changed;
}

public class Status1 : Information<Status1.Codes>
{
    public enum Codes { None = 0, }
    public string AdditionalStatusInformation;

    public Status1()
    {
         StatusCode = Codes.None;
    }
}

public class Status2 : Information<Status2.Codes>
{
    public enum Codes { OK = 0, }

    public Status2()
    {
         StatusCode = Codes.OK;
    }
}

到目前為止一切都很好。 我正在使用Json發送和讀取此信息,並且該方法適用於接收器和發送器。 與Status1和Status2類一起正常工作。

最后,我有一個通用的ErrorReporter類,我想在其中使用Status1或Status2類。 似乎這是不可能的。

public class ErrorReporter<T> where T : Information<T>
{
    public readonly T Info = Activator.CreateInstance<T>();

    public void Update()
    {
        if (Info.Changed)
        {
            Console.WriteLine(Info.StatusCode.ToString());
            Console.WriteLine(JsonConvert.SerializeObject(Info));
        }
    }
}

似乎沒有辦法正確實例化此類。

我嘗試了這些

new ErrorReporter<Status1>()
new ErrorReporter<Status1.Codes>()
new ErrorReporter<Information<Status1.Codes>()

我正進入(狀態

The type 'TestApp.Program.Status1' cannot be used as type parameter 'T' in
the generic type or method 'TestApp.Program.ErrorReporter<T>'.
There is no implicit reference conversion from 'TestApp.Program.Status1' to
'TestApp.Program.Information<TestApp.Program.Status1>'.

或類似的錯誤消息。

我可能應該將ErrorReporter類移到Information類。

但是,從ErrorReporter類實例化新對象的正確方法是什么? 可能嗎?

您需要TInformation<T>派生,這不是您想要的。

我想您需要這個,在這里您需要為泛型提供type參數:

public class ErrorReporter<T, S> where T : Information<S>
{ }

只需多花一點錢,您就可以刪除反射調用:

public class ErrorReporter<T, S> where T : Information<S>, new()
{
    public readonly T Info = new T();
}

問題是您正試圖將T用於兩個目的:

  • 狀態代碼的來源(你打電話StatusCode就可以了)
  • 狀態碼的類型(這是Information<T>的類型參數)

現在,您可以只使ErrorReporter泛型為兩個類型參數:

public class ErrorReporter<TSource, TCode> where TSource : Information<TCode>
{
    public readonly TSource Info = Activator.CreateInstance<TSource>();

    public void Update()
    {
        if (Info.Changed)
        {
            Console.WriteLine(Info.StatusCode.ToString());
            Console.WriteLine(JsonConvert.SerializeObject(Info));
        }
    }
}

然后,您可以使用:

new ErrorReporter<Status1, Status1.Codes>()

或者您可以使它僅在代碼類型中通用,但避免通過反射構造源:

public class ErrorReporter<T>
{
    // You could expose this as a property if you want. I would
    // advise against exposing it as a field
    private readonly Information<T> source;

    public ErrorReporter(Information<T> source)
    {
        this.source = source;
    }

    public void Update()
    {
        if (Info.Changed)
        {
            Console.WriteLine(source.StatusCode.ToString());
            Console.WriteLine(JsonConvert.SerializeObject(source));
        }
    }
}

並將其構造為:

var reporter = new ErrorReporter<Status1.Codes>(new Status1());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM