我可以约束模板参数类来实现其他人支持的接口吗?

时间:2010-06-06 21:20:54

标签: c# generics interface

这个名字有点模糊,所以情况如下:

我正在编写代码以使用某些“轨迹”。轨迹是一个抽象的东西,所以我用不同的接口描述它们。所以我有一个代码:

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; }
    }
    ...
}

轨迹的每个具体实现都将实现上述一些接口。 这是轨迹的具体实现:

    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++; } }
    }

现在,我希望能够推断出有关轨迹的内容,因此,例如,我想支持关于某些轨迹的不同属性的谓词:

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 &lt 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() &lt Value;
        }
    }
}

现在,问题是:如果我想实现AND谓词怎么办? 它会是这样的:

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);
    }
}

我怎么能说:只支持这些轨迹,AND的参数是否合适?

所以我可以写:

var vand = new CountLessThan(32) & new CurrentNormLessThan(4.0);

我认为如果我为每个接口子集创建一个整体接口,我就能做到,但它会变得非常难看。

1 个答案:

答案 0 :(得分:1)

您可以完全消除ICondition,只使用谓词和功能样式。以下是制作静态方法的示例: -

public static Predicate<T> CountLessThan<T> (int value) where T:ICount
{ 
    return (T item) => item.Count < value;
}

以下是你如何使用它: -

Predicate<SimpleTrajectory> anded = x => CountLessThan<SimpleTrajectory>(5)(x) && CountLessThan<SimpleTrajectory>(3)(x);

您还可以创建这样的扩展方法来组合谓词: -

public static Predicate<T> And<T>(this Predicate<T> first, Predicate<T> second)
{
    return (T item) => first(item) && second(item);
}

另一种方法是拥有一个基本的,抽象的,通用的Condition类,从中推导出其他条件,然后在基本条件类中实现And,或者......允许一个流畅的界面,如: -

 ... = new CountLessThan(5).And(new CountLessThan(3))

在T中具有通用性将确保您只能组合具有相同T的条件。