Say I have these three generic class declarations:
public interface IFoo<TId>
{
TId Id { get; set; }
}
public interface IBar<TFoo, TId, TIndex> where TFoo : IFoo<TId>
{
TFoo First { get; set; }
TFoo Second { get; set; }
TIndex Index { get; set; }
}
public interface ISystem<TFoo, TBar, TId, TIndex>
where TFoo : IFoo<TId>
where TBar : IBar<TIndex>
{
ICollection<TFoo> Foos { get; private set; }
ICollection<TBar> Bars { get; private set; }
int CalculateSomething(TFoo foo);
}
I ended up with a lot of type declarations in ISystem to ensure all the constraints are met, e.g. implementing systems should only operate on specific implementations of IFoo and IBar within their systems. However, I am looking for ways to simplify the type declarations and look for solutions where some of the generic types can be inferred without needing to declare them as type parameters.
Note that ISystem implementations may refer to IFoo.Id and IBar.Index when implementing certain methods, like the CalculateSomething() in the example. A concrete implementation might have the following code:
public class Foo : IFoo<Guid>
{
public Guid Id { get; set; }
}
public class Bar : IBar<Foo, Guid, DateTimeOffset>
{
public Foo First { get; set; }
public Foo Second { get; set; }
public DateTimeOffset Index { get; set; }
}
public class MockSystem : ISystem<Foo, Bar, Guid, DateTimeOffset>
{
public ICollection<Foo> Foos { get; private set; }
public ICollection<Bar> Bars { get; private set; }
public int CalculateSomething(Foo foo)
{
// Foo.Id and Bar.Index referenced in this LINQ query
var orderedBars = Bars.Where(b => b.First.Id == foo.Id || b.Second.Id == foo.Id)
.OrderBy(b => b.Index);
int result = 0;
foreach (var bar in orderedBars)
{
// do calculations...
}
return result;
}
}
Questions
Is it possible to:
- Simplify
IBar's type declarations, e.g.IBar<TFoo, TIndex>while keeping it constrained to types ofIFoo<TId>? - Simplify
ISystem's type declarations similarly? e.g.ISystem<TFoo, TBar>and let the compiler/runtime inferTIdandTIndex? In the example class, I'd like to simplify the declaration intopublic class MockSystem : ISystem<Foo, Bar>so the rest of the program infers theIds to beGuids and infers theIndexes to beDateTimeOffsets, without explicitly declaring them.