метод базового класса c# возвращает производный класс

#c# #generics #inheritance

#c# #дженерики #наследование

Вопрос:

Итак, у меня есть приложение, вызывающее ЗАГРУЗКУ веб-сервисов, все из которых имеют класс ответа, каждый класс ответа является производным от ResponseBase

 public abstract record ResponseBase<T>
{
    public HashSet<string> ErrorMessages { get; set; }

    public bool Success { get; set; }

    public virtual string Message => Success ? "Success" : string.Join(", ", ErrorMessages);

    public IEnumerable<T> Results { get; set; }
    public T Result { get; set; }
}
 

Теперь я в настоящее время создаю новые ответы, подобные этому:

 var results = SomeService.GetSomeResults();
return new SomeDerivedResponse() { Success = true; Results = results }
 

Для краткости, ясности и общей чистоты кода я хотел бы сделать что-то вроде:

 var results = SomeService.GetSomeResults();
return new SomeDerivedResponse().WithSuccess(results);
 

WithSuccess() просто присвоит Success = true и Results = results соответственно

Без необходимости помещать один и тот же метод WithSuccess() в каждый из производных классов ответов (их сотни). Я почти добился этого с помощью универсального метода WithSuccess() в базовом классе, но он возвращает базовый класс, а не производный класс, что означает, что у меня есть этот двойной подход:

 return new SomeDerivedResponse().WithSuccess<SomeDerivedResponse>(results);
 

В любом случае я могу либо сообщить компилятору, каков вывод, либо есть лучший способ сделать это?

Комментарии:

1. Почему ваши классы ответов изменчивы?

2. @Dai — я понятия не имею, не мой проект, не мой цирк, не мои обезьяны. Не так, как я бы это сделал. Я просто работаю здесь.

Ответ №1:

Использование общих методов расширения, подобных этому, должно работать:

 public static class Ext
{
    public static T WitSuccess<T, R>(this T t, IEnumerable<R> r) where T : ResponseBase<R>
    {
        // your logic here
        return t;
    }

    public static T WitSuccess<T, R>(this T t, R r) where T : ResponseBase<R>
    {
         // your logic here
        return t;
    }
}
 

И использование:

 public record SomeDerivedResponse : ResponseBase<int>{}
public record SomeDerivedResponse1<T> : ResponseBase<T>{}

new SomeDerivedResponse().WitSuccess(new []{1});
new SomeDerivedResponse1<int>().WitSuccess(1);
 

Комментарии:

1. Что впечатляет, так это то, что вы поняли, что у меня было два типа ответа (IEnumerable и single object) и я закодировал ответ для обоих. Если не считать небольшой орфографической ошибки, сработало как по волшебству. Спасибо.

2. @Tod был рад помочь!