简体   繁体   English

得到警告,“类型参数X隐藏接口X”

[英]Getting warning, 'Type Parameter X Hides Interface X'

This is occurring in Visual Studio 2010. 这是在Visual Studio 2010中发生的。

I'm working with generic methods, and basically losing my intellisense and stopping me from continuing work on this project. 我正在使用通用方法,并且基本上失去了智能,使我无法继续从事该项目。

I basically have the following class: 我基本上有以下课程:

public class SearchRepository : DataRepository<IAudit>
{
    public override IEnumerable<IAudit> RetrieveAll<IAuditSearch>(IAuditSearch searchParameters)
    {
        // CODE GOES HERE
    }

    public override bool Delete<TIAudit>(IAudit audit)
    {
        // CODE GOES HERE
    }
}

This inherits from: 这继承自:

public abstract class DataRepository<T>
{
    public virtual IEnumerable<T> RetrieveAll<U>(U parameter1)
    {
        throw new NotImplementedException();
    }

    public virtual bool Delete<U>(U parameter1)
    {
        throw new NotImplementedException();
    }
}

So Delete works exactly how I would expect it to work. 所以Delete的工作方式与我期望的完全一样。 I have intellisense and it compiles correctly. 我有智能感知,它可以正确编译。 RetrieveAll doesn't work correctly using IAuditSearch. 使用IAuditSearch,RetrieveAll无法正常工作。 If I change it to TIAuditSearch, then it says I'm "There is no suitable method to override". 如果将其更改为TIAuditSearch,则表示“没有合适的方法可以覆盖”。

Not sure what I'm doing wrong, but it's definitely not happy with me. 不知道我在做什么错,但是绝对对我不满意。

UPDATED: changed the virtual to override for the Delete method at the top. 更新:将虚拟更改为覆盖顶部的Delete方法。 That was a mistake. 那是个错误。

You are implicitly hiding (by not overriding) the method signature of 您隐式隐藏(不覆盖)方法的签名

bool Delete<myType>(myType param) { ... }

You can overcome the error my introducing the "new" keyword on the derived class's Delete property. 您可以通过在派生类的Delete属性上引入“ new”关键字来克服该错误。 This explicitly hides the signature and makes everyone happy as it illustrates your intent. 这明确地隐藏了签名,并使每个人高兴,因为它说明了您的意图。

Read the Microsoft documentation at: http://msdn.microsoft.com/en-us/library/aa691135%28v=vs.71%29.aspx . 请阅读Microsoft文档, 网址为: http : //msdn.microsoft.com/zh-cn/library/aa691135%28v=vs.71%29.aspx

You can't define the method public override IEnumerable RetrieveAll(IAuditSearch searchParameters) 您无法定义方法公共重写IEnumerable RetrieveAll(IAuditSearch searchParameters)

The method must still use the U type parameter in place of IAuditSearch. 该方法仍必须使用U类型参数代替IAuditSearch。 Its up to the caller to choose what type to pass. 由呼叫者选择要传递的类型。

You'll probably need to create an ISearch interface and on the base class add where U : ISearch, but even then your subclass would need to accept all ISearch implemenations, not just IAuditSearch. 您可能需要创建一个ISearch接口,并在基类上添加U:ISearch位置,但是即使那样,您的子类也需要接受所有ISearch实现,而不仅仅是IAuditSearch。

Probably the best solution is to define an IAuditSearch repository which is what defines your RetreiveAll method. 最好的解决方案可能是定义一个IAuditSearch存储库,该存储库定义了RetreiveAll方法。

EDIT: I see the question has changed. 编辑:我看到问题已经改变。 You now have the same problem on both methods; 您现在在两种方法上都有相同的问题; you cannot dictate which interface to use when overriding the method, you must maintain the generic type parameter. 您无法指定覆盖该方法时要使用哪个接口,必须维护通用类型参数。

public override IEnumerable<T> RetrieveAll<U>(U parameter1)  { }

public override bool Delete<U>(U parameter1)  { }

Note that you cannot add where clauses to the methods either; 注意,您也不能在方法中添加where子句。 this breaks the Liskov Substitution Prinicple . 这打破了Liskov换人原则 Also I'm not even sure the compiler would allow you to do that. 另外,我什至不确定编译器是否允许您这样做。

Unfortunately, the exact context is not quite clear to me, but I believe your code should look like this: 不幸的是,确切的上下文对我来说还不太清楚,但我相信您的代码应如下所示:

public interface IParameter<T> {
    bool Match(T entry);
}
public abstract class DataRepository<T, TParameter>
    where TParameter : IParameter<T> {
    public abstract IEnumerable<T> RetrieveAll(TParameter parameter1);
    public abstract bool Delete(TParameter parameter1);
}
//
public interface IAudit {/* ... */}
public interface IAuditSearch : IParameter<IAudit> {/* ... */}

public class SearchRepository : DataRepository<IAudit, IAuditSearch> {
    public override bool Delete(IAuditSearch parameter1) {
        // iterate by collection items using parameter matching
        // CODE GOES HERE (DELETE ALL FOUND ENTRIES)
    }
    public override IEnumerable<IAudit> RetrieveAll(IAuditSearch parameter1) {
        // iterate by collection items using parameter matching
        // CODE GOES HERE (RETURN ALL FOUND ENTRIES)
    }
}

Different IAuditSearch implementation will incapsulate a "search by different parameter" logic: 不同的IAuditSearch实现将封装“按不同参数搜索”逻辑:

var guidSearchResult = repository.RetrieveAll(
    new GuidSearch(new Guid("00000000-0000-0000-0000-000000000000")));
var idRangeSearchResult = repository.RetrieveAll(
    new IDRangeSearch(1000, 2000));

where GuidSearch and IDRangeSearch are implemented as: GuidSearch和IDRangeSearch的实现方式为:

public class GuidSearch : IAuditSearch {
    Guid ID;
    public GuidSearch(Guid id) {
        this.ID = id;
    }
    public bool Match(IAudit entry) {
        /* search implementation using ID(Guid)*/
        throw new NotImplementedException();
    }

}
public class IDRangeSearch : IAuditSearch {
    int StartID;
    int EndID;
    public IDRangeSearch(int startId, int endId) {
        this.StartID = startId;
        this.EndID = endId;
    }
    public bool Match(IAudit entry) {
        /* search implementation using ID range (StartID...EndID)*/
        throw new NotImplementedException();
    }
}

Would the following code work instead? 下面的代码可以代替吗?

public class SearchRepository : DataRepository<IAudit, IAuditSearch>
{
    public override IEnumerable<IAudit> RetrieveAll<IAuditSearch>(IAuditSearch searchParameters)
    {
        // CODE GOES HERE
    }

    public override bool Delete<TIAudit>(IAudit audit)
    {
        // CODE GOES HERE
    }
}

public abstract class DataRepository<T, TSearch>
{
    public virtual IEnumerable<T> RetrieveAll(TSearch parameter1)
    {
        throw new NotImplementedException();
    }

    public virtual bool Delete(T parameter1)
    {
        throw new NotImplementedException();
    }
}

So for every instantiation of DataRepository, we declare the result type (T), and the search type (TSearch). 因此,对于DataRepository的每个实例,我们都声明结果类型(T)和搜索类型(TSearch)。

-C -C

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 类型(x)参数返回类型x的方法 - Method with Type (x) parameter returning Type x InvalidCastException:无法将类型x的COM对象转换为接口类型y - InvalidCastException: Unable to cast COM object of type x to interface type y 类型X不能用作通用类型Y中的类型参数T - The type X cannot be used as type parameter T in the generic type Y 警告“Y.cs 中的 X 类型与 Z.dll 中导入的 X 类型冲突” - Warning “The type X in Y.cs conflicts with the imported type X in Z.dll” 对象被实例化但仍然收到警告:“字段&#39;x&#39;永远不会分配给...” - Object is instantiated but still getting Warning: “Field 'x' is never assigned to …” 获取&#39;实体类型的实例&#39;X&#39;&#39;例外 - Getting 'The instance of entity type 'X'' Exception 当x不是变量而是枚举类型时,如何将typeof(x)中的x作为方法参数传递 - How to pass the x in typeof(x) as a method parameter when x is not a variable but an enum type 在 C# 中获取“参数字典包含方法 X 的不可空类型 'System.Int32' 的参数 'ID' 的 null 条目” - Getting “The parameters dictionary contains a null entry for parameter 'ID' of non-nullable type 'System.Int32' for method X” in C# 接口无法解析参数类型 - Interface not resolving for parameter type 不同参数类型的接口 - Interface with different parameter type
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM