Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.70/47: Рейтинг темы: голосов - 47, средняя оценка - 4.70
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614

Создание инстанса типа, который является generic

16.10.2017, 20:02. Показов 9679. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Скажите пожалуйста, я знаю, что мне не получится создать экземпляр класса T, где T - является generic параметром, к примеру, какого нибудь метода. Тоесть внутри этого метода, я не смогу создать инстанс типа T, если только не введу ограничение на where T : new().
А если у меня ограничение на какой-нибудь базовый класс Base, тоесть where T : Base, у которого конструктор имеет параметр, смогу ли я создавать экземпляры T?

Компилятор ругается, но очень хотелось бы провернуть такую фишку...
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
16.10.2017, 20:02
Ответы с готовыми решениями:

Использование byte[] как generic-типа
Подскажите правильное направление в решении такой проблемы. Есть некий класс public class DataQueue<T> : IDisposable where T:...

Generic, определение типа переменной во время выполнения программы
Итак имеется две переменной: одна переменная хранит тип значения (точнее числовое значение одного из типов в моем enum'e) Для ясности...

Объявление обобщённого типа (Generic) для стандартных целочисленных типов
Здравствуйте. Есть класс для вычисления факториала: public class Factorial { long _digit; public...

19
 Аватар для Cupko
658 / 595 / 171
Регистрация: 17.07.2012
Сообщений: 1,682
Записей в блоге: 1
16.10.2017, 20:07
Bretbas, where T : Base, new()
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
16.10.2017, 21:09  [ТС]
Cupko, все равно нельзя создать
0
 Аватар для Cupko
658 / 595 / 171
Регистрация: 17.07.2012
Сообщений: 1,682
Записей в блоге: 1
16.10.2017, 21:14
Цитата Сообщение от Bretbas Посмотреть сообщение
у которого конструктор имеет параметр, смогу ли я создавать экземпляры T?
А, ключевая фраза "имеет параметр"
Нашел такой способ:
C#
1
(T)Activator.CreateInstance(typeof(T), args[])
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
16.10.2017, 21:40  [ТС]
Cupko,
Цитата Сообщение от Cupko Посмотреть сообщение
Нашел такой способ:
C#
1
(T)Activator.CreateInstance(typeof(T), args[])

не...рефлекция...это долго, да и еще не статически типизировано Как же я скучаю по шаблонам C++...

Спасибо, за ответы
0
 Аватар для Cupko
658 / 595 / 171
Регистрация: 17.07.2012
Сообщений: 1,682
Записей в блоге: 1
16.10.2017, 21:41
Люди говорят, что такой костыль в десятки раз медленнее чем вызов конструктора. Но, нормальным способом, я полагаю - никак.
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
16.10.2017, 21:46  [ТС]
Cupko, ну рефлексия - это всегда долго Поэтому согласен с людьми Да и еще раз повторюсь: это не статически типизировано
0
Эксперт .NET
 Аватар для Usaga
14313 / 9393 / 1355
Регистрация: 21.01.2016
Сообщений: 35,424
17.10.2017, 06:55
Bretbas, в C# такой фишки нэма. Тут получается, что если вы знаете сигнатуру конструктора, то вы знаете и тип, которым параметризировали класс. Соответственно, обобщение теряет всякий смысл.

Если есть ну очень острое желание, то можно, надышавшись клеем, сотворить коллекцию фабрик принимающих на вход object[] и выдающих конкретные объекты T. И искать нужную фабрику по параметру дженерика. Оно даст, что вам надо (хоть и обходным путём) и не использует рефлексию, что быстро. Но всё равно это - конина какая-то.

Добавлено через 5 минут
Помните, что параметризация дженериков в .NET происходит в рантайме, потому их возможности сильно ограничены и рядом не стояли с С++, где всё это происходит на этапе компиляции и у компилятора вся информация на руках и он может вытворять всякое непотребство.
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
17.10.2017, 08:20  [ТС]
Usaga,
Цитата Сообщение от Usaga Посмотреть сообщение
Если есть ну очень острое желание, то можно, надышавшись клеем, сотворить коллекцию фабрик принимающих на вход object[] и выдающих конкретные объекты T. И искать нужную фабрику по параметру дженерика. Оно даст, что вам надо (хоть и обходным путём) и не использует рефлексию, что быстро. Но всё равно это - конина какая-то
Можно Но параметры конструктора object[] как то тоже не сильно типизированы

Цитата Сообщение от Usaga Посмотреть сообщение
Помните, что параметризация дженериков в .NET происходит в рантайме
Вроде на этапе компиляции он все статически типизировано, если мы работаем с дженериками, а вот когда уже компилируем, компилятор вроде как срезает тип T, тоесть от List<T> отстается List, и соответственно никакой латентной типизации нельзя в этом случае сделать(если конечно не вставить ограничение с помощью where). По крайней мере у Java так, мне кажется все тоже самое на C#. C++ в этом случае гораздо мощнее, он знает на этапе компиляции и выполнения о типе T все, и ничего не срезает при выполнении. Тоесть от std::vector<T> останется std::vector<T>, а из этого все вытекающие - латентная типизация, создание инстансов, передача неопределенного числа параметров строго типизированно и тд
0
677 / 479 / 216
Регистрация: 06.09.2013
Сообщений: 1,312
17.10.2017, 09:01
Bretbas, если вам нужен именно вызов конструктора с параметрами, то не сможете.
В одной конторе, где я работал было правило, по возможности избегать конструкторов с параметрами и писать метод типа "Initialize", которому параметры передаются для уже сконструированного объекта. Тогда, понятно, создание экземпляров объектов с нужными параметрами легко осуществлялось.
Кликните здесь для просмотра всего текста

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
34
class Base {
    public string Str { get; private set; }
    public Base() { }
    public virtual void Initialize(string str) {
        Str = str;
    }
}
 
class Inherited : Base {        
    public Inherited() { }
    public override void Initialize (string str)
    {
        str += " in inherited";
        base.Initialize (str);
    }
}
 
class GenericFactory<T>  where T : Base, new() {
    public T GetInstance(string str) {
        T result = new T ();
        result.Initialize(str);
        return result;
    }
}
 
static class Program
{               
    static void Main(string[] args)
    {
        GenericFactory<Inherited> f = new GenericFactory<Inherited> ();
        Inherited i = f.GetInstance ("Hello");
        Console.WriteLine (i.Str);
    }       
}
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
17.10.2017, 09:56
Цитата Сообщение от Bretbas Посмотреть сообщение
А если у меня ограничение на какой-нибудь базовый класс Base, тоесть where T : Base, у которого конструктор имеет параметр, смогу ли я создавать экземпляры T?
Нет.
В таком случае передавайте в метод фабрику, которая будет создавать нужный экземпляр:
C#
1
2
3
4
void Foo<T>(Func<T> factory) where T : Base
{
   T instance = factory();
}
C#
1
Foo(() => new Derived(1234));
0
911 / 796 / 329
Регистрация: 08.02.2014
Сообщений: 2,391
17.10.2017, 10:02
C#
1
2
3
4
T TestFunc<T>() where T : class, new()
        {
           return new T();
        }
а дальше только извращения)
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
17.10.2017, 18:17  [ТС]
kolorotur,
Цитата Сообщение от kolorotur Посмотреть сообщение
В таком случае передавайте в метод фабрику
Ага И под каждый тип своя фабрика Не, так не пойдет
Я просто хотел узнать, можно ли сделать что-то типо такого на C#:
(код C++)
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
34
35
36
37
38
39
...
class Base
{
public:
    Base() {}
};
class A : Base
{
public:
    A( int param ) : Base() {}
};
class B : Base
{
public:
    B( std :: string param ) : Base() {}
};
class C : Base
{
public:
    C( std :: string param, float param2 ) : Base() {}
};
 
class Factory
{
public:
    template<typename T, typename... Args, typename std :: enable_if<std :: is_base_of<Base, T> :: value, T> :: type* = nullptr>
    static T* Create( Args... args )
    {
        return new T( std :: forward<Args>( args )... );
    }
};
 
int main()
{
    A* a = Factory :: Create<A>( 3 );
    B* b = Factory :: Create<B>( "string_param" );
    C* c = Factory :: Create<C>( "string_param", 3.4f );
}
...
И понял, что нельзя.
0
Эксперт .NET
 Аватар для Usaga
14313 / 9393 / 1355
Регистрация: 21.01.2016
Сообщений: 35,424
17.10.2017, 18:41
Bretbas, чем этот пример отличается от new и простого конструктора конкретного класса?
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
17.10.2017, 18:52
Цитата Сообщение от Bretbas Посмотреть сообщение
И понял, что нельзя.
Шаблоны в плюсах и генерики в шарпе — очень разные звери.
В плюсах шаблоны — это по сути дела команды найти/заменить для компилятора, они существуют только в тексте программы. Компилятор их просто заменяет на соответствующие типы или перегрузки.
В шарпе генерики — настоящие, они могут принимать в качестве типа-параметра даже такой, которого не существует на стадии компиляции, т.к. конкретный тип под указанный параметр генерируется на стадии выполнения. Потому и компилятор должен быть в состоянии дать гарантию, что после компиляции обобщенный тип или метод может работать с любым типом, подходящим под условия. Отсюда да, больше ограничений.
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
17.10.2017, 19:01  [ТС]
Usaga,
Цитата Сообщение от Usaga Посмотреть сообщение
чем этот пример отличается от new и простого конструктора конкретного класса?
В плане? Я могу через статический шаблонный метод Create фабрики Factory, создать любой тип T, который наследует от Base, причем тип T может иметь любой конструктор, с аргументами, или без, без разницы. Лишь бы public только был

В C# такой можно реализовать, но через рефлексию однозначно, что долго. Да и при передаче параметров в Create на C# будет скорее всего передаваться param object[], что будет не статически типизировано
0
Эксперт .NET
 Аватар для Usaga
14313 / 9393 / 1355
Регистрация: 21.01.2016
Сообщений: 35,424
17.10.2017, 19:07
Цитата Сообщение от Bretbas Посмотреть сообщение
В плане? Я могу через статический шаблонный метод Create фабрики Factory, создать любой тип T, который наследует от Base, причем тип T может иметь любой конструктор, с аргументами, или без, без разницы. Лишь бы public только был
Ну так вы тоже самое можете сделать и простым оператором new, но с меньшим количеством кода. Фабрика подразумевает какой-то особый процесс создания объекта. Но обобщённая фабрика что может сделать особого для каждого отдельно взятого типа класса?
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
17.10.2017, 19:13  [ТС]
Usaga, Вы имеете ввиду зачем писать так:
C++
1
2
3
4
5
...
    A* a = Factory :: Create<A>( 3 );
    B* b = Factory :: Create<B>( "string_param" );
    C* c = Factory :: Create<C>( "string_param", 3.4f );
...
если можно написать вот так:
C++
1
2
3
4
5
...
    A* a = new A( 3 );
    B* b = new B( "string_param" );
    C* c = new C( "string_param", 3.4f );
...
Вы это имеете ввиду?
0
Эксперт .NET
 Аватар для Usaga
14313 / 9393 / 1355
Регистрация: 21.01.2016
Сообщений: 35,424
17.10.2017, 19:14
Хотя такое и может быть полезно. Если создаваемые типы имеют общего предка, через интерфейс которого вновь созданный объект будет конфигурироваться фабрикой как-то. Может в этом что-то и есть.

Добавлено через 32 секунды
Цитата Сообщение от Bretbas Посмотреть сообщение
Вы это имеете ввиду?
Да, но я сам себе уже додумал ответ.
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
17.10.2017, 19:15  [ТС]
Usaga,
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
17.10.2017, 19:15
Помогаю со студенческими работами здесь

Generic коллекция с классом в качестве типа данных. Правильность кода
Здравствуйте. Реализовал вот это. /// &lt;summary&gt; /// Global Object /// &lt;/summary&gt; public static class GO ...

Создание инстанса ADOConnection
Пишу HRESULT hr; hr = m_pConnection.CreateInstance( __uuidof( Connection ) ); if (SUCCEEDED(hr)) { //...

Получить 2 типа из Generic-объекта
Добрый вечер. Мне нужно получить 2 типа (int+double) из одного числа, введённого с клавиатуры. Есть такой набросок, но это явно не...

Создать объект generic типа
Hi. есть абстрактный класс GraphRepresent: public abstract class GraphRepresent {} и несколько классов public class...

Создание объекта в generic
Добрый вечер! Есть интерфейс Num и класс Matrix&lt;T extends Num&gt;. При попытке создать новый объект типа T в Matrix выдаёт ошибку Cannot...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Отправка уведомления на почту при изменении наименования справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере изменения наименования типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
Контроль уникальности заводского номера - вариант №2
Maks 24.03.2026
В отличие от предыдущего варианта добавлено прерывание циклов, также добавлены новые переменные для сохранения контекста ошибки перед прерыванием цикла: Процедура ПередЗаписью(Отказ, РежимЗаписи,. . .
SDL3 для Desktop (MinGW): Вывод текста со шрифтом TTF с помощью библиотеки SDL3_ttf на Си и C++
8Observer8 24.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-text-sdl3-c. zip finish-text-sdl3-cpp. zip
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
Контроль уникальности заводского номера - вариант №1
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере нетипового документа выдачи шин для спецтехники с табличной частью, разработанного в конфигурации КА2. Данные берутся из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru