围绕通用性,我建立了一个简单的社交网络模型,该模型基于人与人之间的关系。
所有这些都存储在容器中。
对于每个容器,我希望能够添加一些验证以检查某些特定约束。
这里可能是过于复杂的模型,但是正如我所说的,我在玩通用性,所以它是故意的:
public interface IContainer<TPerson, TRelation>
where TRelation : IRelation<TPerson>
{
IReadOnlyCollection<TPerson> Persons { get; }
IReadOnlyCollection<TRelation> Relations { get; }
}
public class DefaultContainer<TPerson, TRelation>
: IContainer<TPerson, TRelation>
where TRelation : IRelation<TPerson>
{
private readonly HashSet<TPerson> _persons;
private readonly List<TRelation> _relations;
//...
}
public class DummyValidator<TContainer, TPerson, TRelation>
: IValidator<TContainer, TPerson, TRelation>
where TContainer : IMutableContainer<TPerson, TRelation>
where TRelation : IRelation<TPerson>
{
public bool CanAddRelations(TContainer container, IEnumerable<TRelation> relations)
{
// guard clauses
return true; // whatever
}
public bool CanCreate(IEnumerable<TPerson> persons, IEnumerable<TRelation> relations)
{
// guard clauses
return CanAddRelations(new DefaultContainer<TPerson, TRelation>(), relations);
}
//...
}
[Fact]
public void Test()
{
var sut = new DummyValidator<IContainer<int, IRelation<int>>, int, IRelation<int>>();
sut.CanCreate(Enumerable.Empty<int>(), Enumerable.Empty<IRelation<int>>());
}
看看CanCreate
类的DummyValidator
方法。
它将创建一个新容器(实现TContainer
):
return CanAddRelations(new DefaultContainer<TPerson, TRelation>(), relations);
据我所知,一切都应该很好。但是编译器抱怨说:
无法从“ Alcuin.Graph.Containers.DefaultContainer”转换为“ TContainer”
我的问题是:即使描述了每个通用参数并且总是等效的,为什么还要抱怨呢?
所以我尝试了一些明确的演员调查:
return CanAddRelations((TContainer)new DefaultContainer<TPerson, TRelation>(), relations);
和
return CanAddRelations((IMutableContainer<TPerson, TRelation>)new DefaultContainer<TPerson, TRelation>(), relations);
都失败了,但是:
return CanAddRelations((TContainer)(IMutableContainer<TPerson, TRelation>)new DefaultContainer<TPerson, TRelation>(), relations);
编译并正确运行...
任何人都可以对这里发生的事情有所了解吗? 我是否缺少明显的东西?我是否达到了C#通用引擎的极限?