Получение предупреждения: «Параметр типа X скрывает интерфейс X» - PullRequest
2 голосов
/ 14 марта 2012

Это происходит в Visual Studio 2010.

Я работаю с универсальными методами, и в основном теряю свой смысл и мешаю мне продолжать работу над этим проектом.

У меня в основном следующий класс:

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
    }
}

Это наследуется от:

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();
    }
}

Так что Delete работает именно так, как я и ожидал. У меня есть intellisense, и он правильно компилируется. RetrieveAll не работает правильно, используя IAuditSearch. Если я изменю его на TIAuditSearch, то там будет написано: «Нет подходящего метода для переопределения».

Не уверен, что я делаю неправильно, но он определенно не доволен мной.

ОБНОВЛЕНО: изменен виртуальный метод на переопределение для метода Delete в верхней части. Это была ошибка.

Ответы [ 4 ]

5 голосов
/ 14 марта 2012

Вы неявно скрываете (не переопределяя) сигнатуру метода

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

Вы можете устранить ошибку, введя ключевое слово "new" в свойстве Delete производного класса. Это явно скрывает подпись и делает всех счастливыми, поскольку оно иллюстрирует ваши намерения.

Прочтите документацию Microsoft по адресу: http://msdn.microsoft.com/en-us/library/aa691135%28v=vs.71%29.aspx.

1 голос
/ 14 марта 2012

Вы не можете определить метод public override IEnumerable RetrieveAll (IAuditSearch searchParameters)

Метод должен по-прежнему использовать параметр типа U вместо IAuditSearch. Это до вызывающего абонента, чтобы выбрать, какой тип передать.

Возможно, вам потребуется создать интерфейс ISearch и в базовый класс добавить U: ISearch, но даже тогда вашему подклассу потребуется принять все реализации ISearch, а не только IAuditSearch.

Вероятно, лучшее решение - определить репозиторий IAuditSearch, который определяет ваш метод RetreiveAll.

РЕДАКТИРОВАТЬ: я вижу вопрос изменился. Теперь у вас одна и та же проблема с обоими методами; вы не можете диктовать, какой интерфейс использовать при переопределении метода, вы должны поддерживать параметр универсального типа.

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

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

Обратите внимание, что вы не можете добавлять выражения where к методам; это ломает Лисковский заменитель * * * * * * * *. Также я даже не уверен, что компилятор позволит вам сделать это.

0 голосов
/ 14 марта 2012

Будет ли работать следующий код?

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();
    }
}

Итак, для каждого экземпляра DataRepository мы объявляем тип результата (T) и тип поиска (TSearch).

-C

0 голосов
/ 14 марта 2012

К сожалению, точный контекст мне не совсем понятен, но я считаю, что ваш код должен выглядеть так:

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)
    }
}

Другая реализация IAuditSearch будет инкапсулировать логику «поиск по другому параметру»:

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

где 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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...