Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614

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

16.10.2017, 20:02. Показов 9722. Ответов 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
14321 / 9411 / 1356
Регистрация: 21.01.2016
Сообщений: 35,479
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
14321 / 9411 / 1356
Регистрация: 21.01.2016
Сообщений: 35,479
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
14321 / 9411 / 1356
Регистрация: 21.01.2016
Сообщений: 35,479
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
14321 / 9411 / 1356
Регистрация: 21.01.2016
Сообщений: 35,479
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 22.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в КА2. Задача: контроль и валидация данных табличной части документа перед записью с учетом регламента компании. . .
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2. Задача: разработка отчёта по затраченным материалам за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом. В. . .
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2. Задача: отобразить спецтехнику, которая на данный момент находится в ремонте. Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
Памятка для бота и "визитка" для читателей "Semantic Universe Layer (Слой семантической вселенной)"
Hrethgir 19.04.2026
Сгенерировано для краткого описания по случаю сборки и компиляции скелета серверного приложения. И пусть после этого скажут, что статьи сгенерированные AI - туфта и не интересно. И это не реклама -. . .
Запрет удаления строк ТЧ документа при определённом условии
Maks 19.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "Аккумуляторы", разработанного в конфигурации КА2. У данного документа есть ТЧ, в которой в зависимости от прав доступа. . .
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут Суть: - Группа наркоманов из 10 человек. - Только один инфицирован ВИЧ. - Колются одной иглой. - Колются раз в день. - Колются последовательно через. . .
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru