簡體   English   中英

類型約束C#Generic的無效轉換

[英]Invalid Cast of Type Constrained C# Generic

針對.net 4.0,我正在嘗試構建以下類:

public class ConfigurationElementCollection<TElement, TParent> 
    where TElement : ParentedConfigElement<TParent>, new() 
    where TParent : class
{
    public TParent ParentElement { get; set; }

    protected ConfigurationElement CreateNewElement()
    {
        //**************************************************
        //COMPILER GIVES TYPE CONVERSION ERROR ON THIS LINE!
        //**************************************************
        return new TElement { ParentCollection = this };
    }
}

public class ParentedConfigElement<TParent> : ConfigurationElement where TParent : class
{
    internal ConfigurationElementCollection<ParentedConfigElement<TParent>, TParent> 
        ParentCollection { get; set; }

    protected TParent Parent
    {
        get
        {
            return ParentCollection != null ? ParentCollection.ParentElement : null;
        }
    }
}

正如上面的代碼注釋所示,編譯器給出了一個錯誤:

Cannot implicitly convert type 'Shared.Configuration.ConfigurationElementCollection<TElement, TParent>' to 'Shared.Configuration.ConfigurationElementCollection<Shared.Configuration.ParentedConfigElement<TParent>,TParent>

我不指望這個錯誤,因為編譯器也知道由於我指定的泛型類型約束, TElementShared.Configuration.ParentedConfigElement<TParent>

不過,我想我會明確地說出類型來解決這個問題:

(ConfigurationElementCollection<ParentedConfigElement<TParent>,TParent>) this;

不幸的是,我得到了相同的編譯器錯誤。 為什么會這樣? 我做錯了什么? 如果不采用dynamic類型,我該怎么做才能解決這個問題?

基於https://stackoverflow.com/a/6529618/5071902

protected ConfigurationElement CreateNewElement()
{
    return (TElement)Activator.CreateInstance(typeof(TElement), this);
}

您將需要具有此簽名的構造函數,並設置ParentCollection屬性。

您也可以嘗試使用反射。 看看這個答案https://stackoverflow.com/a/6529622/5071902

您的問題是您有一個CEC<A, B>類型CEC<A, B>並且您嘗試將其分配給CEC<C<A>,B>類型的屬性,這是您無法做到的,與List<string>方式非常相似List<string>即使string派生自object也不能將其分配給List<object>類型的存儲。

不使用隱式運算符或動態的干凈解決方案是使用接口:

public interface IConfigurationElementCollection<TParentedConfig, TParent> 
    where TParentedConfig : ParentedConfigElement<TParent>
    where TParent : class
{
    TParent ParentElement { get; }
}

public class ConfigurationElementCollection<TElement, TParent> : IConfigurationElementCollection<ParentedConfigElement<TParent>, TParent>
    where TElement : ParentedConfigElement<TParent>, new() 
    where TParent : class
{
    public TParent ParentElement { get; set; }

    protected ConfigurationElement CreateNewElement()
    {
        //**************************************************
        //COMPILER NO LONGER GIVES TYPE CONVERSION ERROR 
        //BECAUSE this IMPLEMENTS THE EXPECTED INTERFACE!
        //**************************************************
        return new TElement { ParentCollection = this };
    }
}

public class ParentedConfigElement<TParent> : ConfigurationElement where TParent : class
{
    internal IConfigurationElementCollection<ParentedConfigElement<TParent>, TParent> 
        ParentCollection { get; set; }

    protected TParent Parent
    {
        get
        {
            return ParentCollection != null ? ParentCollection.ParentElement : null;
        }
    }
}

由於ParentedConfigElement的屬性是內部屬性, ParentedConfigElement您也可以將接口設置為內部,以避免將此實現細節暴露給任何消費者,如果您擔心這種情況。

暫無
暫無

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

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