Set Property on a Covariant Interface

故事扮演 提交于 2019-12-11 19:53:16

问题


I have the following covariant interface:

public interface IHierarchical<out T> where T : IHierarchical<T> {
    T Parent { get; }
    IEnumerable<T> Children { get; }
}

I then have the following interfaces which derive from the interface above:

public interface ISiteMapNode<T> : ISiteMapNode where T : ISiteMapNode<T> { }

public interface ISiteMapNode : IHierarchical<ISiteMapNode> {
    string Name { get; set; }
}

Finally I have the following implementation:

public class SiteMapNode : ISiteMapNode<SiteMapNode> {
    public string Name { get; set; }
    public ISiteMapNode Parent { get; }
    public IEnumerable<ISiteMapNode> Children { get; }
}

Now I have a method which takes an argument of type ISiteMapNode and tries to set the Parent property. Obviously this won't work as the Parent property is readonly. I had to remove set to make the IHierachical interface covariant. Is there any way I can do this?


回答1:


No you cannot.

You can think of the out keyword before a type argument as saying that the declared interface will only return (or output) values of the specified type. This is analogous to the in keyword saying that the declared interface will only accept values of the specified type as input.

out = values are ONLY going out
in = values are ONLY going in

Covariant type parameter:

interface IHierarchical<out T>
{
    T Parent
    {
        get; // OK -- it's going out
        set; // ERROR
    }
}

Contravariant type parameter:

interface IHierarchical<in T> 
{
    T Parent
    {
        get; // ERROR
        set; // OK -- it's going in
    }
}

Invariant type parameter: (normal)

interface IHierarchical<T> 
{
    T Parent
    {
        get; // OK
        set; // OK
    }
}

One alternative could be to split the interface into a covariant and a contravariant subinterface. Something like this:

interface IHierarchical<T> : IHierarchicalIn<T>, IHierarchicalOut<T>
{
}

interface IHierarchicalIn<in T>
{
    T Parent { set; }
}

interface IHierarchicalOut<out T>
{
    T Parent { get; }
}

class Node : IHierarchical<Node>
{
    public Node Parent
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }
}

I don't really see a use for that though.



来源:https://stackoverflow.com/questions/26276231/set-property-on-a-covariant-interface

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