【问题标题】:Shorter path to generic constraints通向通用约束的更短路径
【发布时间】:2020-11-20 22:01:28
【问题描述】:

我为了好玩而进行了一些通用过滤,然后来到了某种“和”过滤器,其中约束变成了使通用代码工作的地狱。这些是我最初的通用接口:

interface ISpecification<in T>
{
    bool IsSatisfied(T obj);
}

class ColoredSpecification : ISpecification<IColored>
{
    readonly Color color;

    public ColoredSpecification(Color color)
    {
        this.color = color;
    }

    public bool IsSatisfied(IColored iColored)
    {
        return iColored.Color == color;
    }
}

interface IFilter<T>
{
    IEnumerable<T> Filter(IEnumerable<T> items, ISpecification<T> specification);
}

class ProductFilter : IFilter<Product>
{
    public IEnumerable<Product> Filter(IEnumerable<Product> items, ISpecification<Product> specification)
    {
        return items.Where(p => specification.IsSatisfied(p));
    }
}

class GenericFilter<T> : IFilter<T>
{
    public IEnumerable<T> Filter(IEnumerable<T> items, ISpecification<T> specification)
    {
        return items.Where(p => specification.IsSatisfied(p));
    }

    // It is used like this
    static IEnumerable<Product> A()
    {
        var colorSpec = new ColoredSpecification(Color.Black);
        var products = new[]
        {
            new Product { Color = Color.White },
            new Product { Color = Color.Black },
            new Product { Color = Color.Beige }
        };

        return new GenericFilter<Product>().Filter(products, colorSpec);
    }
}

然后,有龙

class AndSpecification<T1, T2, T3, T4, T5> : ISpecification<T1>
    where T1 : T2, T3
    where T4 : ISpecification<T2>
    where T5 : ISpecification<T3>
{
    readonly T4 u;
    readonly T5 v;

    public AndSpecification(T4 u, T5 v)
    {
        this.u = u;
        this.v = v;
    }

    public bool IsSatisfied(T1 obj)
    {
        return u.IsSatisfied(obj) && v.IsSatisfied(obj);
    }
}

它是这样使用的:

var colorSpec = new ColoredSpecification(Color.Black);
var sizeSpec = new SizedSpecification(5);
var andSpec = new AndSpecification<Product, IColored, ISized, ColoredSpecification, SizedSpecification>(colorSpec, sizeSpec);

var products = new[]
{
    new Product { Color = Color.White },
    new Product { Color = Color.Black },
    new Product { Color = Color.Beige }
};

return new GenericFilter<Product>().Filter(products, andSpec);

有没有合理的方法来完成这项工作?我的意思是,像 3 个泛型参数是“合理的”,或者只有 1 个,但看起来不可能

【问题讨论】:

  • 您能否删除where T1 : T2, T3,然后将ISpecification&lt;T1&gt; 用于其他约束?

标签: c# linq filtering


【解决方案1】:

为了好玩的一些通用过滤

fun的答案就是多次调用.Where()

您的IFilter 接口及其实现不知道ISpecification 参数的实现类型。您的AndSpecification 类型也不需要知道。

class AndSpecification<T1,T2,T3> : ISpecification<T1> where T1:T2,T3 {
    AndSpecification(ISpecification<T2> u, ISpecification<T3> v){ ... }
    bool IsSatisfied(T1 obj) => u.IsSatisfied(obj) && v.IsSatisfied(obj);
}

【讨论】:

  • 谢谢。我发现构造函数仍然非常冗长,所以,我决定只使用: static IEnumerable AndFilter(IEnumerable items, ISpecification u, ISpecification v) where T1 : T2, T3 { return items.Where(obj => u.IsSatisfied(obj) && v.IsSatisfied(obj)); }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 2016-05-28
  • 1970-01-01
相关资源
最近更新 更多