Invalid Cast of Type Constrained C# Generic

*爱你&永不变心* 提交于 2020-02-03 04:59:52

问题


Targeting .net 4.0, I'm trying to build the following classes:

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;
        }
    }
}

As the code comment above indicates, the compiler gives an error:

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

I don't expect this error, because the compiler also knows that TElement is a Shared.Configuration.ParentedConfigElement<TParent> due to the generic type constraint I specified.

Still, I figure I will expressly cast the type to get past this issue:

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

Unfortunately, I get the same compiler error. Why is this happening? What did I do wrong? And without resorting to dynamic types, what can I do to fix this?


回答1:


Your problem is that you have a type CEC<A, B> and you trying to assign it to a property of type CEC<C<A>,B> which you can't do, in much the same way as List<string> cannot be assigned to storage of type List<object> even though string derives from object.

A clean solution without using implicit operators or dynamic is to use an interface:

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;
        }
    }
}

Since the property in ParentedConfigElement is internal, you can also make the interface internal to avoid exposing this implementation detail to any consumers, if that sort of thing is a concern for you.




回答2:


Based on https://stackoverflow.com/a/6529618/5071902

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

You will need a constructor with this signature, setting the ParentCollection property.

You can try using reflection too. Take a look at this answer https://stackoverflow.com/a/6529622/5071902



来源:https://stackoverflow.com/questions/32514439/invalid-cast-of-type-constrained-c-sharp-generic

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!