Can I constrain a template parameter class to implement the interfaces that are supported by other?
- by K. Georgiev
The name is a little blurry, so here's the situation:
I'm writing code to use some 'trajectories'. The trajectories are an abstract thing, so I describe them with different interfaces. So I have a code as this:
namespace Trajectories {
public interface IInitial < Atom >
{
Atom Initial { get; set; }
}
public interface ICurrent < Atom >
{
Atom Current { get; set; }
}
public interface IPrevious < Atom >
{
Atom Previous { get; set; }
}
public interface ICount < Atom >
{
int Count { get; }
}
public interface IManualCount < Atom > : ICount < Atom >
{
int Count { get; set; }
}
...
}
Every concrete implementation of a trajectory will implement some of the above interfaces.
Here's a concrete implementation of a trajectory:
public class SimpleTrajectory < Atom > : IInitial < Atom >, ICurrent < Atom >, ICount < Atom >
{
// ICount
public int Count { get; private set; }
// IInitial
private Atom initial;
public Atom Initial { get { return initial; } set { initial = current = value; Count = 1; } }
// ICurrent
private Atom current;
public Atom Current { get { return current; } set { current = value; Count++; } }
}
Now, I want to be able to deduce things about the trajectories, so, for example I want to support predicates about different properties of some trajectory:
namespace Conditions
{
public interface ICondition < Atom, Trajectory >
{
bool Test(ref Trajectory t);
}
public class CountLessThan < Atom, Trajectory > : ICondition < Atom, Trajectory >
where Trajectory : Trajectories.ICount < Atom >
{
public int Value { get; set; }
public CountLessThan() { }
public bool Test(ref Trajectory t)
{
return t.Count < Value;
}
}
public class CurrentNormLessThan < Trajectory > : ICondition < Complex, Trajectory >
where Trajectory : Trajectories.ICurrent < Complex >
{
public double Value { get; set; }
public CurrentNormLessThan() { }
public bool Test(ref Trajectory t)
{
return t.Current.Norm() < Value;
}
}
}
Now, here's the question: What if I wanted to implement AND predicate?
It would be something like this:
public class And < Atom, CondA, TrajectoryA, CondB, TrajectoryB, Trajectory > : ICondition < Atom, Trajectory >
where CondA : ICondition < Atom, TrajectoryA >
where TrajectoryA : // Some interfaces
where CondB : ICondition < Atom, TrajectoryB >
where TrajectoryB : // Some interfaces
where Trajectory : // MUST IMPLEMENT THE INTERFACES FOR TrajectoryA AND THE INTERFACES FOR TrajectoryB
{
public CondA A { get; set; }
public CondB B { get; set; }
public bool Test(ref Trajectory t){
return A.Test(t) && B.Test(t);
}
}
How can I say: support only these trajectories, for which the arguments of AND are ok?
So I can be able to write:
var vand = new CountLessThan(32) & new CurrentNormLessThan(4.0);
I think if I create an orevall interface for every subset of interfaces, I could be able to do it, but it will become quite ugly.