如何编写通用方法?(关于IT技术)

3

这是我先前有关规范模式的增强问题 - 如何动态组合条件?.

我正在尝试将OnSaleSpecificationForBook方法变成通用的。原因是音频CD逻辑也需要类似的规范,而且BookAudioCD都实现了ISellingItem接口。

规范

public class OnSaleSpecificationForBook : Specification<Book>
{
    public override bool IsSatisfiedBy(Book product)
    {
        return product.IsOnSale;
    }
}

我尝试创建如下的通用方法,但它会抛出以下错误:

找不到'T'类型或命名空间名称

带编译错误的代码

public class OnSaleSpecification : Specification<T>
{
    public override bool IsSatisfiedBy(T item)
    {
        return item.IsOnSale;
    }
}

问题

  1. 这个错误的原因是什么?
  2. 我们如何使这个方法变成通用的?

注意:我正在使用 .Net 4.0。但我想知道是否与 .Net 2.0 相比需要进行任何差异处理。

概述

public interface ISellingItem
{
    bool IsOnSale { get; set; }
    double Price { get; set; }
}

public abstract class Specification<T>
{
    public abstract bool IsSatisfiedBy(T obj);
}

客户端

class Program
{       
    static void Main(string[] args)
    {
        List<Book> list = new List<Book>();

        Book p1 = new Book(false, 99);
        Book p2 = new Book(true, 99);
        Book p3 = new Book(true, 101);

        list.Add(p1);
        list.Add(p2);
        list.Add(p3);

        var specification = new OnSaleSpecificationForBook();
        List<Book> selectedList =
            ProductFilterHelper.GetProductsUisngDynamicFilters(list, specification);
    }
}

public static class ProductFilterHelper
{
    public static List<Book> GetProductsUisngDynamicFilters(List<Book> productList, Specification<Book> productSpecification)
    {
        return productList.Where(p => productSpecification.IsSatisfiedBy(p))
                          .ToList();
    }
}

实体

public class Book : ISellingItem
{
    public bool IsOnSale { get; set; }
    public double Price { get; set; }

    public Book(bool isOnSale, double price)
    {
        this.Price = price;
        this.IsOnSale = isOnSale;
    }
}

public class AudioCD : ISellingItem
{
    public bool IsOnSale { get; set; }
    public double Price { get; set; }

    public AudioCD(bool isOnSale, double price)
    {
        this.Price = price;
        this.IsOnSale = isOnSale;
    }
}

2个回答

3

在编译器知道它是一个ISellingItem之前,您需要指定通用参数类型正在实现什么。 您可以使用where T: ISellingItem子句来实现此目的:

public class OnSaleSpecification<T> : Specification<T> where T : ISellingItem
{
    public override bool IsSatisfiedBy(T item)
    {
        return item.IsOnSale;
    }
}

1
除非您也将 OnSaleSpecification 设为泛型,否则此代码无法编译。 - Ian McLaird
Lijo:我已经编辑了答案。@Ian McLaird:发现得好。谢谢。 - CassOnMars
1
你不能扩展一个未绑定的泛型类型。所有类型参数(在这种情况下是 <T>)都必须在 : 之前定义或者是一个明确已知的类型。 - Ian McLaird
2
还要注意,在这个特定情况下,你可以将它设置为OnSaleSpecification : Specification<ISellingItem>,而不会对方法的功能造成任何损失。然而,如果你这样做了,就会失去添加其他可能真正关心实际类型的方法的能力。 - Ian McLaird
@Lijo,在您在本问题的评论中提供的链接中,被接受的答案通过代码证明了这一点。 - Ian McLaird
显示剩余2条评论

0

你的 OnSaleSpecification 类需要定义泛型参数 T,并将其限制为 ISellingItem 接口

public class OnSaleSpecification<T> : Specification<T> where T : ISellingItem
{
    public override bool IsSatisfiedBy(T item)
    {
        return item.IsOnSale;
    }
}

没有对 T 设置约束条件,因为它没有 IsOnSale 属性,所以这行代码无法工作。 - Lee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接