c#7当使用泛型用于方法参数时我得到方法的类型参数'U'的约束必须匹配接口的约束

EiE*_*Guy -3 c# generics interface .net-core asp.net-core-mvc-2.0

我正在尝试创建一个接口和一个具体的实现,其中Interface是泛型类型,其中一个方法有一个泛型参数.

我想保留GetPagedList方法参数resourceParams,这样我就可以为接口的不同实现传递不同的resourceParams对象.

使用下面显示的代码时,我收到错误;

方法'ShippingServicesRepository.GetPagedList(U)'的类型参数'U'的约束必须与接口方法IBaseRepository.GetPagedList(U)的类型参数'U'的约束匹配.请考虑使用显式接口实现

这是我的界面;

public interface IBaseRepository<T> 
{
    bool Save();
    bool Exists(int recordId);
    bool MarkForDeletion(int recordId);
    PagedList<T> GetPagedList<U>(U resourceParams) where U : class;
    T Get(int id);
    void Add(T record);
    void Update(T record);
}
Run Code Online (Sandbox Code Playgroud)

这是我的实施;

public class ShippingServicesRepository<T> : IBaseRepository<T> 
{

    //                      /--- GetPagedList is what is throwing the error
    //                      |
    public PagedList<T> GetPagedList<U> (U resourceParams) where U : ShippingServicesResourceParameters
    {
        try
        {

            var collectionBeforePaging =
                _manifestContext.ShippingServices
                .ApplySort(resourceParams.OrderBy, _propertyMappingService.GetPropertyMapping<ShippingServicesDto, ShippingServices>());
            if (!string.IsNullOrEmpty(resourceParams.SearchQuery))
            {
                var searchQueryForWhereClause = resourceParams.SearchQuery.Trim().ToLowerInvariant();
                collectionBeforePaging = collectionBeforePaging
                    .Where(a => a.ReferenceId.ToLowerInvariant().Contains(searchQueryForWhereClause));
            }
            collectionBeforePaging = collectionBeforePaging
                .Where(d => d.DeleteFlag == resourceParams.DeleteFlag);

            return (dynamic)PagedList<ShippingServices>.Create(collectionBeforePaging,
                resourceParams.PageNumber,
                resourceParams.PageSize);
        }
        catch (Exception)
        {
            _logger.LogError(500, "ShippingServices Filter [{FILTER}]", resourceParams);
            throw;
        }
    }

    public void Add(T record)
    {
        ...
    }

    public bool Exists(int recordId)
    {
        ...
    }

    public T Get(int id)
    {
        ...
    }

    public bool MarkForDeletion(int recordId)
    {
        ...
    }

    public bool Save()
    {
        ...
    }

    public void Update(T record)
    {
        ...
    }

}
Run Code Online (Sandbox Code Playgroud)

这是我的ShippingServicesResourceParameters类

public class ShippingServicesResourceParameters : BaseResourceParameters
{
    public string FileName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这是ShippingServicesResourceParameters继承的BaseResourceParameters类

public class BaseResourceParameters
{
    private int _pageSize;
    public int PageNumber { get; set; } = 1;
    public int PageSize
    {
        get
        {
            return _pageSize;
        }
        set
        {
            _pageSize = (value > MaxPageSize) ? MaxPageSize : value;
            if (value == 0)
            {
                _pageSize = 10; // set a default size
            }
        }
    }

    public int MaxPageSize { get; set; } = 20;
    public bool DeleteFlag { get; set; }
    public string SearchQuery { get; set; }
    public string OrderBy { get; set; } = "Id";
    public string Fields { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我没有将"where U:ShippingServicesResourceParameters"添加到具体实现中的方法签名和接口中的"where U:class",我得到一个"无法从方法组转换为字符串..."的错误首先在具体实现中使用resourceParams变量.(在".ApplySort(resourceParams.OrderBy")

我在这里错过了什么?

Eri*_*ert 6

让我们做你应该做的事情,并制作一个演示问题的最小程序:

interface I 
{
    void M<U>(U u) where U : class;
}
class D 
{
    public void O() {}
}
class C : I
{
    public void M<U>(U u) where U : D
    {
        u.O();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个错误,因为C没有实现I.它没有实现I,因为:

I i = new C();
i.M<Giraffe>(new Giraffe());
Run Code Online (Sandbox Code Playgroud)

现在我们有一只长颈鹿被传递C.M<Giraffe>(Giraffe)C.M<U>要求U是D.所以这是非法的.

我们无法解决这个问题:

    public void M<U>(U u) where U : class
    {
        u.O();
    }
Run Code Online (Sandbox Code Playgroud)

因为现在我们可以D.O()打电话给长颈鹿类型的接收器.

因此我们必须像这样解决它:

interface I 
{
    void M<U>(U u) where U : D;
}
class D 
{
    public void O() {}
}
class C : I
{
    public void M<U>(U u) where U : D
    {
        u.O();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们都很好.

需要使实现约束与接口约束匹配,就像您需要满足接口强加的所有其他要求一样.接口是合同.你必须完成讨价还价的结束.

我注意到这是错误消息所说的:你必须匹配约束,而你不是这样做的.注意错误信息; 大多数时候他们会告诉你什么是错的.