C# 抽象泛型方法

8

C#, .Net 3.5

我正在尝试创建一个具有通用方法的基类。继承它的类应该指定该方法的类型。

这是为了创建管理过滤器的类。

所以我有:

 public abstract class FilterBase {
   //NEED Help Declaring the Generic method for GetFilter
   //public abstract IQueryable<T> GetFilter<T>(IQueryable<T> query);
 }

 public class ProjectFilter:FilterBase {
   public IQueryable<Linq.Project> GetFilter(IQueryable<Linq.Project> query) {
     //do stuff with query
     return query;
   }
 }

 public class ProjectList {
   public static ProjectList GetList(ProjectFilter filter) {
     var query = //....Linq code...

     query = filterCriteria.GetFilter(query); 

   }

 }

看起来很简单,但是我在FilterBase中的GetFilter抽象方法中无法正确使用语法。

编辑

理想情况下,希望仅将方法保持为通用方法而不是类。如果不可能,请告诉我。

3个回答

16

将FilterBase类本身变成泛型。

public abstract class FilterBase<T>
{
    public abstract IQueryable<T> GetFilter(IQueryable<T> query);
}

这将使您能够像这样创建ProjectFilter类:

public class ProjectFilter : FilterBase<Linq.Project>
{
    public override IQueryable<Linq.Project> GetFilter(IQueryable<Linq.Project> query)
    {
        //do stuff with query
        return query;
    }
}

那行得通,但我必须使类成为泛型吗?我不能只保持方法是泛型的吗?我问这个问题的原因是可能会有多个针对同一类的GetFilter,它们使用不同于“Linq.Project”的IQueryable<T>。 - B Z
2
@B Z:你只能将方法设为泛型,但这样它就必须一直保持泛型状态直到被调用。你不能从非泛型类派生并在方法中尝试分配泛型类型,如你在问题中所尝试的那样。在这种情况下,调用者必须向该方法提供类型。 - Mark Seemann
1
@B Z:如果类不是泛型的,则方法的签名包含未限定的泛型。你尝试的是同时使用构造类型覆盖该方法。这多多少少相当于尝试同时覆盖成员并更改其签名 - 无论是否有泛型,都不允许这样做。Jon Skeet的书中有一个完整的章节介绍泛型,但我不能确定它是否确切地回答了你的问题。 - Mark Seemann
你的代码语法不正确。GetFilter 不应该是泛型的,而且在 ProjectFilter 中缺少 "override" 关键字。 - Bryan Watts
@BZ:这并不是一个限制。根据你的描述,抽象方法显然不是通用的,因为它只允许一组类型。将该方法改为通用的完全违背了其公共契约,所以你甚至不应该考虑如何实现这样的技术。如果你需要一个非通用的基础类型,请让FilterBase<T>继承自FilterBase类型。 - Sam Harwell
显示剩余2条评论

4
 public abstract class FilterBase<T> {
    public abstract IQueryable<T> GetFilter<T>(IQueryable<T> query);
 }

2
当然,您可以拥有一个抽象的通用方法:
public abstract class FilterBase {
    public abstract IQueryable<T> GetFilter<T>(IQueryable<T> query);
}

问题在于它并不意味着你想要的。它可以被称为任何 T。特别地,以下内容必须正常工作,因为 ProjectFilter 派生自 FilterBase
FilterBase fb = new ProjectFilter(...);
IQueryable<string> query = ...;
IQueryable<string> filter = fb.GetFilter<string>(query);

因此,FilterBase 不能只实现 GetFilter<Linq.Project>。它需要实现 GetFilter<string>GetFilter<int> 等等;简而言之,GetFilter<T>。因此,您可以看到这不是一种限制。


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