繁体   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