类型参数'T'与外部类型'的类型参数同名'...

时间:2015-01-06 23:29:39

标签: c# .net generics

我真的很困惑。你能帮我么?见代码;

我正在尝试为我的解决方案构建一个只使用一个存储库的结构。要查询特定查询,我使用IQueryBuilder。实际上我正在寻找对象查询的好东西,我找到了这个here

public interface IQueryBuilder<T> where T : class
{
    IQueryBuilder<T> Where(Expression<Func<T, bool>> predicate);
    IQueryBuilder<T> Include(Expression<Func<T, object>> path);
    IQueryBuilder<T> OrderBy(Expression<Func<T, object>> path);
    IQueryBuilder<T> OrderByDescending(Expression<Func<T, object>> path);
    IQueryBuilder<T> Page(int page, int pageSize);

    T FirstOrDefault();
    Task<T> FirstOrDefaultAsync();

    List<T> ToList();
    Task<List<T>> ToListAsync();

    int Count();
    Task<int> CountAsync();
}

此处的存储库代码。

public interface IRepository<T> : IDisposable
{
    IQueryBuilder<T> Query<T>() where T : class;
}

到目前为止对我这么好。在按F6之前我非常高兴,因为存储库界面中的Query,我得到以下错误。

警告1类型参数“T”与外部类型“IRepository”中的类型参数同名IRepository.cs 13 32 VideoK2.Repository

顺便提一下这个话题有几个问题。但我无法理解他们。无法弄清楚我的话题。所以,抱歉再次询问。

3 个答案:

答案 0 :(得分:9)

编译器认为此定义不明确:

public interface IRepository<T> : IDisposable
{
    IQueryBuilder<T> Query<T>() where T : class;
}

要了解原因,请问自己这个示例问题(我将使用两个随机选择的类):如果您有一个IRepository<string>的实例,您是否可以在其上调用Query<StreamReader>?< / p>

如果答案是肯定的,这意味着方法T的类型参数Query<T>与接口T的类型参数IRepository<T>不同。它们是两个独立的类型参数。如果是这种情况,那么只需将其中一个更改为其他内容,以明确您的意图:

public interface IRepository<T> : IDisposable
{
    IQueryBuilder<TResult> Query<TResult>() where TResult : class;
}

如果答案为否,则表示接口T的类型参数IRepository<T>指示方法Query的返回类型。如果是这种情况,那么该方法不应声明自己的类型参数,因为该类型已经具有该信息。

public interface IRepository<T> : IDisposable 
    where T : class
{
    IQueryBuilder<T> Query();
}

答案 1 :(得分:5)

此代码:

public interface IRepository<T> : IDisposable
{
    IQueryBuilder<T> Query<T>() where T : class;
}

基本上可以改写为:

public interface IRepository<TObject> : IDisposable
{
    IQueryBuilder<TResult> Query<TResult>() where TResult : class;
}

摆脱错误。问题是第二个<T>影响第一个。

但是...... 你看到这个新代码的问题了吗?


我猜你的真正含义是:

public interface IRepository<T> : IDisposable
    where T : class
{
    IQueryBuilder<T> Query();
}

或者这个:

public interface IRepository : IDisposable
{
    IQueryBuilder<T> Query<T>() where T : class;
}

保留这两个通用参数在这种情况下没有多大意义,因为其中一个从未使用过。

答案 2 :(得分:0)

好。答案后,我看到了正确的方法。我使用Generic Repository和Object Query的原因是我想为所有查询使用一个存储库。所以这迫使我使用Generic Repository。 (因为我以前的练习)。但在此示例中,不需要使用通用存储库。

我想写一些代码以获取更多信息。

此对象查询的接口

public interface IQueryBuilder<T>
{
    IQueryBuilder<T> Where(Expression<Func<T, bool>> predicate);
    IQueryBuilder<T> Include(Expression<Func<T, object>> path);
    IQueryBuilder<T> OrderBy(Expression<Func<T, object>> path);
    IQueryBuilder<T> OrderByDescending(Expression<Func<T, object>> path);
    IQueryBuilder<T> Page(int page, int pageSize);

    T FirstOrDefault();
    Task<T> FirstOrDefaultAsync();

    List<T> ToList();
    Task<List<T>> ToListAsync();

    int Count();
    Task<int> CountAsync();
}

及其实施

public class QueryBuilder<T> : IQueryBuilder<T>
{
    DdContext applicationDbContext;
    private IQueryable<T> query;

    public QueryBuilder(DbContext applicationDbContext)
    {
        this.applicationDbContext = applicationDbContext;
        this.query = this.context.Set<T>();
    }

    public IQueryBuilder<T> Where(Expression<Func<T, bool>> predicate)
    {
        this.query = this.query.Where(predicate);

        return this;
    }

    public IQueryBuilder<T> Include(Expression<Func<T, object>> path)
    {
        this.query = this.query.Include(path);
        return this;
    }

    public IQueryBuilder<T> OrderBy(Expression<Func<T, object>> path)
    {
        this.query = this.query.OrderBy(path);
        return this;
    }

    public IQueryBuilder<T> OrderByDescending(Expression<Func<T, object>> path)
    {
        this.query = this.query.OrderByDescending(path);
        return this;
    }

    public IQueryBuilder<T> Page(int page, int pageSize)
    {
        this.query = this.query.Skip(page * pageSize).Take(pageSize);
        return this;
    }

    public T FirstOrDefault()
    {
        return this.query.FirstOrDefault<T>();
    }

    public Task<T> FirstOrDefaultAsync()
    {
        return this.query.FirstOrDefaultAsync();
    }

    public List<T> ToList()
    {
        return this.query.ToList();
    }

    public Task<List<T>> ToListAsync()
    {
        return this.query.ToListAsync();
    }

    public int Count()
    {
        return this.query.Count();
    }

    public Task<int> CountAsync()
    {
        return this.query.CountAsync();
    }
}

这是Repository接口

public interface IRepository
{
    IQueryBuilder<T> Query<T>();
}

及其实施

public class Repository : IRepository
{
    private DBContext Contex { get; set; }

    public Repository(DBContext ctx)
    {
        this.Contex = ctx;
    }

    public QueryBuilder.IQueryBuilder<T> Query<T>()
    {
        return new QueryBuilder.QueryBuilder<T>(this.Contex);
    }
}

这些行是样本用法

public class HomeController : Controller
{

    private IRepository repo = new Repository(new SampleContext());

    public HomeController(){}

    // GET: Home
    public ActionResult Index()
    {
        var author = repo.Query<Author>().ToList();

        var authors = repo.Query<Author>().ToListAsync();

        var authors = repo.Query<Author>().Where(a => a.Name != "Orwell").ToList();

        var authors = repo.Query<Author>().Where(a => a.Name != "Orwell").ToListAsync();

        var author = repo.Query<Author>().FirstOrDefault();

        var author = repo.Query<Author>().FirstOrDefaultAsync();

        var author = repo.Query<Author>().Where(a => a.Name == "Orwell").FirstOrDefault();

        var author = repo.Query<Author>().Where(a => a.Name == "Orwell").FirstOrDefaultAsync();

        var book = repo.Query<Book>().Where(b => b.Title == "The Wasp Factory").FirstOrDefault();

        return View(author);
    }
}