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

У меня есть следующие классы:

public abstract class TableStorageItem
{
    public TableStorageItem() { }
}
public abstract class TableStorage<T> where T : TableStorageItem, new()
{
    public async Task CheckInitializeAsync(CancellationToken cancellationToken = default)
    {
     ...
    }
}
public class TableStorageCleanerTask<T, U>
    where T : TableStorage<U>
    where U : TableStorageItem, new()
{
    public TableStorageCleanerTask() { }

    public async Task InitializeAsync(CancellationToken cancellationToken = default)
    {
        await T.CheckInitializeAsync(cancellationToken)
    }
}

Я хотел бы вызвать CheckInitializeAsync изнутри InitializeAsync, но у меня есть ошибка компилятора CS0704:

Невозможно использовать невиртуальный элемент в T, поскольку это параметр типа.

Я уверен, что есть способ сделать это, но я не могу его понять.

CheckInitializeAsync не статичен. Почему вы ожидали, что T.CheckInitializeAsync(cancellationToken) сработает?
Sweeper 25.03.2024 12:57

Вы неверно процитировали текст ошибки. В нем должен быть поиск слова: Cannot do non-virtual member lookup in 'T' because it is a type parameter Лучше всего скопировать и вставить текст ошибки, когда задаете вопрос.

Wyck 25.03.2024 13:20

Я подозреваю, что отрицательные отзывы вызваны тем фактом, что текст ошибки и номер строки точно объясняют проблему. И быстрый поиск в Интернете укажет на решение. Одна из веских причин для отрицательного голосования — «не демонстрирует никаких исследовательских усилий».

Wyck 25.03.2024 13:22

@Wyck Я, конечно, провел исследование, в том числе Bing Copilot, потому что он потрясающе находит ответы. Но вы правы, возможно, я не скопировал/вставил текст ошибки.

Olivier MATROT 25.03.2024 16:07
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Согласно комментарию @Sweeper, метод CheckInitializeAsync не является статическим, поэтому его нельзя вызвать для класса; только против объекта, созданного из этого класса.

public class TableStorageCleanerTask<T, U>
    where T : TableStorage<U>
    where U : TableStorageItem, new()
{
    private T tableStorage;
    public TableStorageCleanerTask(T tableStorage)
    {
        this.tableStorage = tableStorage;
    }

    public async Task InitializeAsync(CancellationToken cancellationToken = default)
    {
        await tableStorage.CheckInitializeAsync(cancellationToken)
    }
}
Ответ принят как подходящий

вы пытаетесь вызвать метод экземпляра, например статический метод. Вам необходимо объявить свою функцию следующим образом, которая принимает экземпляр TableStorage, или вы можете создать новый экземпляр, а затем вызвать функцию CheckInitializeAsync() в InitializeAsync():

public class TableStorageCleanerTask<T, U>
where T : TableStorage<U>
where U : TableStorageItem, new()
{
    public TableStorageCleanerTask() { }

    public async Task InitializeAsync(T storage, CancellationToken cancellationToken = default)
    {
        await storage.CheckInitializeAsync(cancellationToken);
    }
}

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