Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
1 / 1 / 0
Регистрация: 08.07.2015
Сообщений: 14

Передача типа производного класса как type parameter в generic методе в методе базового класса

05.06.2023, 00:42. Показов 826. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте.

Есть классы: абстрактный A и, его производные, B, C и т.д.. В классе A есть метод DoSomething, в ходе выполнения которого объект должен возвращаться в пул объектов ссылкой именно на свой класс (не базовый), чтобы, в дальнейшем, избежать даункастов.
Проблема в том, что я не могу понять как в методе базового класса передать тип производного класса в generic метод.

Примерный код, для наглядности:
C#
1
2
3
4
5
6
7
8
9
10
public abstract class A
{
    public virtual void DoSomething()
    {
        //...
 
        // Здесь должен быть не A, а его производный класс
        ObjectPooling<A>.Return(this);
    }
}
У меня есть "кастыльное" решение этой проблемы: создание абстрактного метода, допустим, ReturnToPool, запускаемого из DoSomething, который будет реализовываться в производных классах и иметь одну единственную строку, например, в классе С: "ObjectPooling<С>.Return(this);".
Все же хотелось бы узнать, есть ли правильное решение данной проблемы, чтобы избежать лишней писанины и для общего развития.

Заранее благодарю.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.06.2023, 00:42
Ответы с готовыми решениями:

Как получить доступ к свойству класса у базового класса в методе
public abstract class Unit { public string _name { get; protected set; } public int _health { get; protected set;...

Создание указателя типа базового класса на экземпляр производного класса
Добрый день! Иногда видел коды, где создавался указатель типа базового класса на объект класса - наследника, для чего это может применяться?

Передача класса как параметра в методе
Добрый вечер. У меня проблема. foreach (Form item in Application.OpenForms) { if(item is frm_fac) ...

6
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,230
05.06.2023, 02:59
Этот код, конечно, можно поломать словив InvalidCastException, если в объявлении одного класса подсунуть параметром типа другой A<TPoolResident>, но это оставляем на совести разработчика.
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,230
05.06.2023, 04:32
Например, так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var sample = new MyResident();
sample.DoSomething();
 
var otherSample = new MyOtherResident();
otherSample.DoSomething();
 
 
public abstract class A<TPoolResident> where TPoolResident : A<TPoolResident>
{
    public virtual void DoSomething()
    {
        //...
 
        // Здесь должен быть не A, а его производный класс
        var obj = ObjectPooling<TPoolResident>.Return((TPoolResident)this);
        Console.WriteLine(obj.GetType().Name);
    }
}
 
 
public static class ObjectPooling<T>
{
    public static T Return(T obj) => obj;
}
 
 
public class MyResident : A<MyResident>
{
}
 
public class MyOtherResident : A<MyOtherResident>
{
}
Добавлено через 2 минуты
Этот код, конечно, можно поломать словив InvalidCastException, если в объявлении одного класса подсунуть параметром типа другой A<TPoolResident>, но это оставляем на совести разработчика.

Добавлено через 1 час 32 минуты
Ну и, по-хорошему, нужно применить Template Method, чтобы наследникам не приходилось помнить о вызове ObjectPooling.Return
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class A<TPoolResident> where TPoolResident : A<TPoolResident>
{
    public void DoSomething()
    {
     
        DoSomethingCore();
        // Здесь должен быть не A, а его производный класс
        var obj = ObjectPooling<TPoolResident>.Return((TPoolResident)this);
        Console.WriteLine(obj.GetType().Name);
    }
  
    protected virtual void DoSomethingCore() 
    {
 
     }
}
1
1 / 1 / 0
Регистрация: 08.07.2015
Сообщений: 14
05.06.2023, 15:39  [ТС]
IamRain, большое спасибо за ответ, однако ваше предложение не решает ключевой проблемы: наличия даункастов. Они просто переезжают из момента получения объекта из пула (изначальный код) в момент возвращения объекта в пул ("var obj = ObjectPooling<TPoolResident>.Return((TPoolResident)this);").

Извиняюсь, если это я ввел вас в заблуждение, как-то неправильно обрисовав ситуацию. Основная моя проблема - даункасты.
Код моего примера подразумевает, что я вынужден возвращать в пул объекты как классы A и, затем, при получении этих же объектов из пула, даункастить в их действительные классы: B, С, так далее.

Как я упоминал в первом посте, решение этой проблемы у меня есть, просто оно мне не нравится, и хотелось бы узнать, есть ли варианты лучше.
На всякий случай оставлю код под спойлером, может кому пригодится.
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract class A
{
    public virtual void DoSomething()
    {
        //...
 
        ReturnToPool();
    }
 
    public abstract void ReturnToPool();
}
 
public class B: A
{
    //...
 
    public override void ReturnToPool()
    {
        ObjectPooling<B>.Return(this);
    }
}
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,230
05.06.2023, 16:12
Цитата Сообщение от Zug-Zug Посмотреть сообщение
наличия даункастов.
Ну так а вы что хотели? Базовый класс понятия не имеет о том, какие конкретные классы будут его наследовать. Чтобы предоставить эту информацию, нужно использовать параметры типов, то есть сделать базовый открытым обобщенным типом.
Цитата Сообщение от Zug-Zug Посмотреть сообщение
Код моего примера подразумевает, что я вынужден возвращать в пул объекты как классы A и, затем, при получении этих же объектов из пула, даункастить в их действительные классы: B, С, так далее.
А теперь это делается автоматически, без необходимости писать однотипную реализацию в каждом наследнике, видите разницу?

Добавлено через 1 минуту
Небольшая правка с выводом типа:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class A<TPoolResident> where TPoolResident : A<TPoolResident>
{
    public void DoSomething()
    {
     
        DoSomethingCore();
        // Здесь должен быть не A, а его производный класс
        var obj = ObjectPooling<TPoolResident>.Return((TPoolResident)this);
        Console.WriteLine(typeof(TPoolResident).Name);
    }
  
    protected virtual void DoSomethingCore() 
    {
 
     }
}
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
05.06.2023, 16:38
Цитата Сообщение от Zug-Zug Посмотреть сообщение
В классе A есть метод DoSomething, в ходе выполнения которого объект должен возвращаться в пул объектов
Два вопроса:
1. Как объект изначально попадает в пул?
2. Почему работа с пулом — зона ответственности самого класса, а не того, кто хочет кэшировать его экземпляры?
0
1 / 1 / 0
Регистрация: 08.07.2015
Сообщений: 14
05.06.2023, 19:19  [ТС]
Здравствуйте.
Цитата Сообщение от kolorotur Посмотреть сообщение
1. Как объект изначально попадает в пул?
Система пула объектов, по запросу, либо создает новый экземпляр, либо берет один из раннее созданных и уже вернувшихся.
Цитата Сообщение от kolorotur Посмотреть сообщение
2. Почему работа с пулом — зона ответственности самого класса, а не того, кто хочет кэшировать его экземпляры?
Потому что объект должен храниться в пуле ссылкой именно на этот класс.

Добавлено через 21 минуту
Правильней, наверно, было бы ответить, что у меня нет полного контроля над объектом, только над некоторыми его компонентами.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
05.06.2023, 19:19
Помогаю со студенческими работами здесь

Как сложить объект базового класса с объектом производного(наследуемого класса)
Как умножить объект базового класса с объектом производного(наследуемого класса): ozenka - объект базового класса, а ves- производного ...

Передача значения из конструктора производного класса в конструктор базового
Всем привет, такой вопрос: есть ли возможность передать значение из производного конструктора в базовый таким образом: static...

как сделать чтобы объект производного класса сам себя добавлял в список или массив указателей базового класса?
я хотел так, но программа просто падает void Student::add(Base** head) { cout &lt;&lt; &quot;I here&quot; &lt;&lt; endl; this-&gt;setName(); //все...

Полиморфизм. В коллекции базового типа выполнить метод производного класса.
Добрый день! Есть класс Animal, от него унаследован класс Predator. Есть коллекция экземпляров класса Animal, в ней же содержатся...

Приём константных векторов класса, как аргументов в методе другого класса
Есть такой класс: class Order { private: int numberOrder; map &lt;string, int&gt; catalogDish; double totalCost; public: ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru