Как использовать универсальный тип в универсальном методе

ИЗМЕНИТЬ, чтобы показать реальный пример

Как я могу вызвать универсальную функцию из универсального типа, переданного в функцию? Кажется, это должно быть интуитивно понятно, но я не могу заставить его работать.

Например, могу ли я вызвать функцию cache.ResetCache () в LocalDataObjectEngine ниже?

Я получаю сообщение об ошибке: «Тип T нельзя использовать в качестве параметра».

public interface ISimpleCache<T1>
{    
    ...
    void ResetCache<T>() where T : T1;
}

internal class LocalDataObjectEngine_Cache : ISimpleCache<IBrokeredDataObject>
{
    ISimpleCache<IBrokeredDataObject> _cache;

    ...

    public void ResetCache<T>() where T : IBrokeredDataObject
    {
        //logic here
    }

    ...
}

public partial class LocalDataObjectEngine : IEngine
{
    ISimpleCache<IBrokeredDataObject> _cache  = new LocalDataObjectEngine_Cache();

    public void ResetCache<T>() where T : IBrokeredDataObject
    {
        _cache.ResetCache<T>();
    }
}

}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
3 106
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Я не уверен, что происходит, если только в вашем определении IBrokeredDataObject что-то не написано. То, что вы написали, мне кажется правильным и компилируется.

[Отредактировано в соответствии с редакцией OP]

Прежде всего, зачем вам указывать универсальный тип в ваших методах? В классе уже указан универсальный тип, вы получите доступ к нему в своих методах:

public interface ISimpleCache<T1>
{    
    ...
    void ResetCache();
}

что значительно упрощает класс, реализующий интерфейс:

internal class LocalDataObjectEngine_Cache : ISimpleCache<IBrokeredDataObject>
{
    ISimpleCache<IBrokeredDataObject> _cache;

    ...

    public void ResetCache();
    {
        //logic here with access to IBrokeredDataObject if needed
    }

    ...
}

то же самое касается последнего метода, просто вызовите

_cache.ResetCache();

однако, если вам действительно нужно указать универсальный тип в методах по какой-либо причине, выполните следующие действия.


Давайте начнем:

Почему бы вам не использовать T1 в методе вместо того, чтобы указывать T должно быть похоже на T1?

public interface ISimpleCache<T1>
{    
    ...
    void ResetCache<T1>();
}

В вашем LocalDataObjectEngine_Cache вам не нужно снова указывать T, просто используйте IBrokeredDataObject (если вы не реализуете метод и щелкните правой кнопкой мыши имя интерфейса, чтобы выбрать «Реализовать интерфейс», он запишет его, как показано ниже:

internal class LocalDataObjectEngine_Cache : ISimpleCache<IBrokeredDataObject>
{
    ISimpleCache<IBrokeredDataObject> _cache;

    ...

    public void ResetCache<IBrokeredDataObject>();
    {
        //logic here
    }

    ...
}

Затем из вашего последнего класса просто вызовите его снова, указав фактический класс, которым вы хотите, чтобы T был:

public partial class LocalDataObjectEngine : IEngine
{
    ISimpleCache<IBrokeredDataObject> _cache  = new LocalDataObjectEngine_Cache();

    public void ResetCache<IBrokeredDataObject>()
    {
        _cache.ResetCache<IBrokeredDataObject>();
    }
}

Я хотел различать T1 как базовый объект кеша и T как типизированный объект, производный от T, поскольку в кеше может находиться от 0 до n различных типов объектов, все производные от IBrokeredDataObject, но я хочу указать один типа смыть.

johnc 17.01.2009 10:03

Поэтому сброс кеша ResetCache <IBrokeredDataObject> не будет соответствовать моим требованиям, поскольку я не могу указать движку удалить все DerivedDataObjectType1, а не DerivedDataObjectType2 из кеша.

johnc 17.01.2009 10:04

Пока ваш класс реализует IBrokeredDataObject, вы можете использовать его при объявлении объекта _cache. ISimpleCache <SomeClassThatImplementsTheInterface> _cache = new ... будет работать.

mbillard 17.01.2009 15:38

После удаления ..., ссылки на IEngine, и предоставления пустого интерфейса IBrokeredDataObject ваш код компилируется без каких-либо проблем.

Пожалуйста, предоставьте короткий, но полный пример, который компилирует не. В идеале создайте новый проект с одним файлом, поместите туда весь свой код и сделайте его как можно проще, показывая ту же ошибку. Затем просто вырезайте и вставьте сюда. Таким образом, нам не нужно исправлять "..." и т. д. Или удалять ссылки на интерфейсы, для которых у нас нет объявлений.

Спасибо, я опубликовал ответ, именно ваша ссылка на IEngine помогла мне найти виновника

johnc 17.01.2009 14:25
Ответ принят как подходящий

Нашел, ссылка Джона Скита на удаление IEngine указала мне в правильном направлении, была

void ResetCache<T>() where T : IDataObject

на IEngine (IDataObject является базой для IBrokeredDataObject), который я изменил на

void ResetCache<T>() where T : IBrokeredDataObject

Спасибо всем за то, что терпели мою ошибку, +1 всем вам

Другие вопросы по теме