0

There is a code in which there is this implementation:

using System;
using System.Collections.Generic;

namespace ConsoleApp{

    public interface IModel { } 

    public class Model : IModel { }

    public interface IDataBuilder<T> where T : IModel
    {
        T Build();
    }

    public interface IActionBuilder<T> where T : IModel
    {
        object BuildAction(T model);
    }

    public interface ISet<T> where T : IModel
    {
        IDataBuilder<T> DataBuilder { get; } 
        IActionBuilder<T> ActionBuilder { get;}
    }

    public class Builder
    {
        private List<ISet<IModel>> _dataBuilders;
        public void AddSet(ISet<IModel> _dataBuilder)
        {
            _dataBuilders.Add(_dataBuilder);
        }
    }

    public class MySet : ISet<Model>
    {
        public IDataBuilder<Model> DataBuilder => throw;    
        public IActionBuilder<Model> ActionBuilder  => throw;
    } 

    public class Program 
    {
        static void Main(string[] args)
        {
            var builder = new Builder(); 
            builder.AddSet( new MySet() );
        }      
    }   
} 

And in the line

builder.AddSet( new MySet() );

I get this error:

Program.cs(56, 29): [CS1503] Argument 1: cannot convert from 'ConsoleApp.MySet' to 'ConsoleApp.ISet<ConsoleApp.IModel>'

Naturally, I can just directly cast:

var builder = new Builder(); 
builder.AddSet( (ISet<IModel>)new MySet() );

But in my case this is not an option, I need it to work out architecturally without such a cast.

Playing with covariance and invariance has not helped unfortunately.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
Alex
  • 131
  • 3
  • 3
    Your cast would fail anyway - an `ISet` isn't an `ISet`. It can't be, because otherwise you'd be able to use `mySet.ActionBuilder.BuildAction(new SomeOtherModel())` - which I wouldn't expect to work with an `IActionBuilder`. – Jon Skeet Jan 03 '18 at 15:49
  • 2
    You can't make `ISet` covariant due to `IActionBuilder` which could be made contravariant but not covariant due to the `model` parameter of `BuildAction`. – Lee Jan 03 '18 at 15:52
  • Your question is a standard "I want to use my type in a variant way even though it isn't legal to do so" question. See marked duplicate for discussion as to why this sort of thing doesn't work. – Peter Duniho Jan 04 '18 at 04:48

0 Answers0