Klamsi
Klamsi

Reputation: 906

Casting from concrete Type to interface

I have following code that does not compile

using System.Collections.Generic;

public interface IElement
{
}

public class AElement : IElement
{
    public void DoSomethingSpecial()
    { }
}

public class Container<TElement>
{
    public List<TElement> Elements { get; } = new();
}



public class Program
{
    public static Container<IElement> GetContainer()
    {
        var concreteContainer = new Container<AElement>();
        concreteContainer.Elements.ForEach(e => e.DoSomethingSpecial());
        
        return concreteContainer; // Cannot implicitly convert type 'Container<AElement>' to 'Container<IElement>'
    }
    
    public static void Main()
    {
        var myContainer = GetContainer();
    }
}

I read documentation about Covariance, Invariance, Contravariance and out Types. And I am more confused than at the beginning.

Whats the way to fix this?

Code online: https://dotnetfiddle.net/85AgfT

Upvotes: 0

Views: 243

Answers (2)

Klamsi
Klamsi

Reputation: 906

I finally got it working

using System.Collections.Generic;

public interface IContainer<out TElement>
{
}

public interface IElement
{
}

public class AElement : IElement
{
    public void DoSomethingSpecial()
    { }
}

public class Container<TElement> : IContainer<TElement>
{
    public List<TElement> Elements { get; } = new();
}



public class Program
{
    public static IContainer<IElement> GetContainer()
    {
        var concreteContainer = new Container<AElement>();
        concreteContainer.Elements.ForEach(e => e.DoSomethingSpecial());
        
        return concreteContainer;
    }
    
    public static void Main()
    {
        var myContainer = GetContainer();
    }
}

Make Container also an Interface and use an out Type parameter

Upvotes: 0

ElConrado
ElConrado

Reputation: 1638

You need to generate implicit conversion operator:

public class Container<IElement>
{
    public List<IElement> Elements { get; } = new List<IElement>();

    public static implicit operator Container<IElement>(Container<AElement> v)
    {
        //here you need to create Container<IElement> with your Container<AElement> 'v' values
        return new Container<IElement>();
    }
}

Upvotes: 1

Related Questions