Когда инстанциируются Generics? [re: Что можно почитать ..]
про ТВОЮ реализацию массива как класса с форума ФДС тред я не забуду никогда, я тебя уверяюО чём идёт речь, интересно?
Что конкретно тебе интересно, ты так и не написал, нужно просто что-то «крутое» и невъебное. Читай книжки, желательно не на русском языке.а) я написал, меня интересуют подходы к реализации указанных фич.
б) Если я возьму Джейн Эйр на французском, вряд ли найду там что-то по существу. Что мне нужно читать книжки статьи я знаю и без подобных глупых советов. Сюда я написал, чтобы кто-нибудь посоветовал конкретные книжки/статьи по этим темам.
в) твои сарказмы совершенно не уместны; сгинь
а) я написал, меня интересуют подходы к реализации указанных фич.Я тоже написал куда копать, но ты ведь не умеешь искать инфу, правда? Иначе не спрашивал бы.
То, о чем ты тут спрашиваешь — детский лепет для любого человека, который занимается программированием более-менее серьезно.
С3В короче.
б) Если я возьму Джейн Эйр на французском, вряд ли найду там что-то по существу.Автор о программизме не писала, ты прав.
Что мне нужно читать книжки статьи я знаю и без подобных глупых советов. Сюда я написал, чтобы кто-нибудь посоветовал конкретные книжки/статьи по этим темам.По каким? Про GC ты ниже написал, что уже сам нашел.
Про полиморфизм? Я про него нигде не читал, точнее прочитал, что есть в объектах указатели на таблицы виртуальных функций, дальше позапускал программки, посмотрел отладчиком куда эти указатели ведут, посмотрел, что там написано.
Да, неужели в Страуструпе нету?
в) твои сарказмы совершенно не уместны; сгиньЭто не сарказм, я в открытую ставлю под сомнение твою компетентность как программиста.
О чём идёт речь, интересно?http://www.fds-net.ru/forum/index.php?showtopic=58750&hl...
там не про массивы
там не про массивывектор — не массив? Не важно, не о структурах данных речь, а о том, что человек за несколько лет не может понять как работает его (не поймите превратно) инструмент.
Моё исходное мнение:
на generics в принципе можно написать математику в самом общем виде. Задумано, сделано.
Вопрос в теме:
можно ли улучшить?
Утверждение :
generics не предназначены для этой цели (заметь, оффтоповое)
generics != templates (что и так очевидно)
templates лучше подходит (тоже ежу понятно, чего тут доказывать-то)
в заголовке темы не видит C#/.NET (ну понятно, тяжело догадаться, что это означает, что в задачу поставлена реализация именно на сабже)
доказывает, что generics не предназначены для того, для чего предназначены templates
исходит он из того, что у них разная реализация, чего, разумеется, недостаточно для совершения такого вывода
затем низкая производительность .NET, чего, разумеется, тоже недостаточно.
Вопрос:
что тебе не нравится?
Твоя позиция в том треде рухнула после того, что ты сказал, что generics инстанциируются во время компиляции. Все, этого достаточно. Ку-ку.
исходит он из того, что у них разная реализацияНу значит ты до сих пор не понял, что тебе хотели сказать.
что тебе не нравится?мне как раз нравится, как некоторые люди любят выпячивать свою некомпетентность наружу.
на generics в принципе можно написать математику в самом общем виде. Задумано, сделано.в .net-е, MATH лучше не заносить в описание класса Vector, т.к. это никаких бонусов не дает, в отличие от плюсов, но усложняет использование векторов - например, усложняет такую странную операцию, как сложение векторов из двух разных математик
Вопрос в теме:
можно ли улучшить?
generics инстанциируются во время компиляцииОчевидно, мы с тобой по-разному воспринимаем эту фразу.
Ну значит ты до сих пор не понял, что тебе хотели сказать.
Ну так объясни. Может всё-таки перейдём на приват?
мне как раз нравится, как некоторые люди любят выпячивать свою некомпетентность наружу
Навскидку:
Можно при помощи reflection инстанцировать generic c каким-нибудь произвольным (ну без учета constraints) System.Type
using System;
namespace CsPlay
{
class CsPlay
{
class Generic<T> where T: IDisposable
{
}
static void Main(string[] args)
{
var gtype = typeof(Generic<>);
try
{
var type = gtype.MakeGenericType(typeof(Uri;
Console.WriteLine(" sucks");
}
catch (Exception)
{
Console.WriteLine(" sucks");
}
}
}
}
Навскидку:Он этот форум не читает. Хотя этот тред я ему покажу.
Навскидку:Теперь перечитай что пишет тебе , а именно слова в скобках. Понимаешь, что значит произвольный System.Type без учета constraints? Uri не реализует IDisposable.
http://www.fds-net.ru/forum/index.php?showtopic=58750&vi...
Можно при помощи reflection инстанцировать generic c каким-нибудь произвольным (ну без учета constraints) System.Type
using System;
namespace CsPlay
{
class CsPlay
{
class Generic<T> where T: IDisposable
{
}
static void Main(string[] args)
{
var gtype = typeof(Generic<>);
try
{
var type = gtype.MakeGenericType(typeof(Uri;
Console.WriteLine(" sucks");
}
catch (Exception)
{
Console.WriteLine(" sucks");
}
}
}
}
Ты плохо понимаешь: вот ты у себя можешь написать любую программу, пусть она выводит на экран хоть что Балмер нищий. Дела это не меняет.
вердикт: sucks
Да. Причем кто-то из нас понимает ее неправильно. А может вообще не понимает
generics инстанциируются во время компиляцииОчевидно, мы с тобой по-разному воспринимаем эту фразу.
в принципе можно написать математику в самом общем видеменя одного прет от этого утверждения?
Ты плохо понимаешь: вот ты у себя можешь написать любую программу, пусть она выводит на экран хоть что Балмер нищий. Дела это не меняет.ты вот вместо того, чтобы стебаться, лучше пытайся сформулировать - как оно на самом деле обстоит.
и тебе польза будет:
мозги прочистятся,
знания лучше по полочкам разложатся,
другие подскажут тебе слабые места в твоих формулировках
и другим поможет тоже самое сделать.
Да. Причем кто-то из нас понимает ее неправильно. А может вообще не понимаеткакое кстати твое мнение в двух словах, что там и как происходит с generics.
Понимаешь, что значит произвольный System.Type без учета constraints? Uri не реализует IDisposable.Тогда пусть учится писать однозначно. Для меня там было написано, что можно взять произвольный System.Type, которые не обязательно удовлетворяет ограничениям (о чём написано в скобках). На это я и привёл тебе контрпример.
Что такое инстанцирование типа во время выполнения же вообще не понятно. Он имел ввиду, что можно во время выполнения создать тип с определёнными женерик параметрами? Так в C# с помощью Reflection можно создать вообще любой тип во время выполнения. В чём смысловая нагрузка этого утрверждения-то?
какое кстати твое мнение в двух словах, что там и как происходит с generics.а причем тут мое мнение?
Это я к тому, что мое мнение тут спрашивать ни к чему. КАК оно реализовано я попросту не знаю. Но что generics в отличие от шаблонов компилируются в MSIL и инстанциируются уже на стадии выполнения, это мне известно.
В чём смысловая нагрузка этого утрверждения-то?Не, ну вот у тебя реально объем памяти ограничен походу, одно сказали, другое уже вылетело в соседнее ухо.
Вот я тот тред не перечитывал, не знаю, из какого контекста ты выдрал это предложение. Но могу предположить, что все из того же: чел пытается донести, что в .NET generics'ы подставляются во время выполнения: и ты можешь в этом убедиться, написав код.
ты вот вместо того, чтобы стебаться, лучше пытайся сформулировать - как оно на самом деле обстоит.А что там непонятно? Чувак сам же пишет в constraints IDisposable и сам же потом пытается подставить туда Uri. ЧТО тут может быть непонятно?
и тебе польза будет:
мозги прочистятся,
знания лучше по полочкам разложатся,
другие подскажут тебе слабые места в твоих формулировках
и другим поможет тоже самое сделать.
чел пытается донести, что в .NET generics'ы подставляются во время выполнения
а) куда подставляются?
б) если это осмысленно, какое это имеет значение при реализации вектора над произвольным полем?
в) ты не претендуешь на гуру CLR, а мнение 'а по поводу того, для чего не предназначены generic'и в свете существования работающего кода меня не интересует; и всё это обсуждение выходит за рамки вопроса, поставленного в этой теме
либо давай продолжим в личке (и отчитаемся потом тут, если это кому-то надо либо прекратим эту дискуссию
А что там непонятно? Чувак сам же пишет в constraints IDisposable и сам же потом пытается подставить туда Uri. ЧТО тут может быть непонятно?[censored]
Ты только что отвечал на пост, где я сказал, что "(ну без учета constraints)" воспринял как пояснение, а не как уточнение к слову "произвольным".
UPD. Кстати, когда, если не на этапе компиляции, происходит собственно подстановка параметров в generic'и?В частности это предложение меня напугало. И не надо тут про другое понимание затирать. Все и так ясно.
[censored]Да вообще покакать как ты там все понял, но ты написал код примерно следующий
Ты только что отвечал на пост, где я сказал, что фразу " Можно при помощи reflection инстанцировать generic c каким-нибудь произвольным (ну без учета constraints) System.Type" я воспринял следующим образом: Не запрещено во время выполнения с помощью Reflection инстанцировать generic с произвольным System.Type, обойдя ограничения constraints.
if (false)и приводил его как аргумент.
прав оппонент
else
я прав
Отлично, вот и ответь на этот вопрос.
а) куда подставляются?ладно, инстанциируются, так понятнее? Ведь для тебя же стараюсь, а ты начинаешь к словам цепляться.
б) если это осмысленно, какое это имеет значение при реализации вектора над произвольным полем?Да никакого может и не имеет. Прочитай мой сааааамый первый пост про этот тред. Я говорю, что ты ничего не смыслишь в теме, в которой крутишься уже несколько лет.
если это кому-то надотолько тебе может быть, но ты же не хочешь брать. Ты лишь распространяешь лучи бреда вокруг себя.
Всё, хватит редактировать посты
Я говорю, что ты ничего не смыслишь в теме, в которой крутишься уже несколько лет.Чего именно я не смыслю?
Отлично, вот и ответь на этот вопрос.Ога. Т.е. у тебя сейчас наш разговор как ветром из головы сдуло? Я уже об этом упоминал.
Ладно. Вот исправь свою программу (убери where к черту проводишь инстанцирование. НА ЭТАПЕ КОМПИЛЯЦИИ ТЫ ЕГО ПРОВОДИШЬ?
Чего именно я не смыслю?Ответы на вопросы первого поста неизвестны разве что тем, кто не смыслит в своей области.
НА ЭТАПЕ КОМПИЛЯЦИИ ТЫ ЕГО ПРОВОДИШЬ?ДА.
ДА.И этот человек спрашивает в чем он не смыслит. Да ты даже не можешь отличить в программе действия, которые выполняются на этапе компиляции от тех, что происходят уже на стадии выполнения программы.
Вообще это я просто тебя обхитрил так. То не вопрос был. Точнее ответ на него для каждого разумного человека и так ясен. А именно, все, что касается Reflection — это на этапе выполнения, это уже не компиляция программы. А твой ответ как раз является твоим признанием в кретинизме.
И этот человек спрашивает в чем он не смыслит. Да ты даже не можешь отличить в программе действия, которые выполняются на этапе компиляции от тех, что происходят уже на стадии выполнения программы.
Не, никак не осилишь?
ты вот вместо того, чтобы стебаться, лучше пытайся сформулировать - как оно на самом деле обстоит.
и тебе польза будет:
мозги прочистятся,
знания лучше по полочкам разложатся,
другие подскажут тебе слабые места в твоих формулировках
и другим поможет тоже самое сделать.
Ты так и не ответил на вопрос, когда оно происходит по-твоему и в чём его суть?
Не, никак не осилишь?Происходит во время выполнения, потому что доступно из Reflection, который по определению уже стадия выполнения. Так лучше? Просто надеялся, что ты догадаешься, зря наверное.
Ты мне так и не ответил на вопрос, когда оно происходить по-твоему?
Так. И уясни для себя такой момент: тут ты задаешь вопросы, ты плаваешь в теме, так что не тебе у меня приказным тоном требовать пояснений. Будь благодарен той крупице знания, которой я соблаговолил с тобой поделиться и будь поспокойнее, ты все же к учителю обращаешься
Из Reflection в .NET доступно всё. Можно сделать новую сборку с новыми типами во время выполнения. И там будут проверяться соответствие фактических параметров формальным. На основании этого ты будешь утверждать, что в C# соответствие фактических параметром формальным производится на этапе выполнения?
так что не тебе у меня приказным тоном требовать поясненийУкажи, пожалуйста, где ты увидел приказной тон?
Вот твой приказной тон:
И уясни для себя такой момент
На основании этого ты будешь утверждать, что в C# соответствие фактических параметром формальным производится на этапе выполнения?Проверка соответствия фактических параметров формальным не требует дополнительного кода на этапе компиляции, это просто средство предохранения от ошибок. Т.е. аналогия тобой проведена неудачно, значит она не подкрепляет твоей точки зрения, а значит, подтверждает мое мнение не только о твоей некомпетентности, но и ставит под сомнение вообще твои аналитические способности.
Укажи, пожалуйста, где ты увидел приказной тон?Я имел в виду вот это:
Не, никак не осилишь?Просто когда я чего-то не понимаю и пытаюсь у форумцев узнать ответ, я веду себя поспокойнее и не начинаю требовать у всех объяснять мне _почему_ они правы. Я обычно склонен верить на слово, если сам чувствую себя слабым в вопросе, а тебе впору чувствовать себя слабым в обсуждаемых вопросах.
Ты так и не ответил на вопрос, когда оно происходит по-твоему и в чём его суть?
а причем тут мое мнение?потому что в дискуссию стоит вступать если есть свое мнение, пусть наивное, но свое.
только свое мнение ты сможешь отстаивать, приводить какие-то доводы и т.д.
Это я к тому, что мое мнение тут спрашивать ни к чему. КАК оно реализовано я попросту не знаю.не знаешь - придумай.
придумай модель - как оно могло быть - этого обычно уже достаточно для понимания.
Звезд ты с неба не хватаешь, чего уж там. Мой пойнт был в том, что задача, которую ты себе поставил, чудовищна в своей сумасбродной ненужности. Или ты до сих пор этим своим вектором пользуешься?
Проверка соответствия фактических параметров формальным не требует дополнительного кода на этапе компиляции, это просто средство предохранения от ошибок. Т.е. аналогия тобой проведена неудачно, значит она не подкрепляет твоей точки зрения, а значит, подтверждает мое мнение не только о твоей некомпетентности, но и ставит под сомнение вообще твои аналитические способности.
Вообще-то компилятору C# не требуется никакого дополнительного кода на этапе компиляции для инстанцирования generic'ов. Он компилирует в промежуточный код.
Вообще-то компилятору C# не требуется никакого дополнительного кода на этапе компиляции для инстанцирования generic'ов. Он компилирует в промежуточный код.Вооот, это я тебе и пытался донести. Понял? А что тогда означало вот это твое восклициние:
В общем, я тебя покидаю, мне разбираться в бардаке в твоей голове не хочется. Как говорили на баш. орге, чем больше таких как ты, тем более ценен я как специалист.
Я сказал "ДА", потому что в выходном коде уже не тип List<>, а тип List<string>. И в дальнейшем с ним может много разного происходить. Либо JIT скомпилирует его методы перед их исполнением (как любые другие методы либо ngen (или что-то аналогичное) задолго до этого исполнения, либо интерпретатор вообще не будет ничего компилировать и изменять, а просто выполнит IL. Когда, например, в последнем случае будет происходить по-твоему инстанцирование типа?
В этом ты соглашаешься, что в случае с generic'ами тоже не требуется дополнительный код.Я же тебе говорю, ты не понимаешь текст. С generic'ами не требуется на этапе компиляции, требуется на стадии выполнения. Для проверки типов не требуется никогда. Поэтому присутствие функционала в Reflection подтверждает гипотезу о том, что инстанцирования generic'ов происходят на этате выполнения и ничего не говорит относительно проверки типов.
интерпретатор вообще не будет ничего компилировать и изменять, а просто выполнит IL. Когда, например, в последнем случае будет происходить по-твоему инстанцирование типа?на стадии компиляции как ты говоришь, ага.
Теперь понял, почему твои аналогии - фуфло?
C++ .NET
инстанцирование во время компиляции во время выполнения, да еще и неизвестно,
генерится куча однотипного кода нужен ли будет этот код (если есть
например, ты когда-нибудь where T : IDisposable, то обращения к
писал DLL, экспортирующую шаблон? типу T будут только исходя из этого
интерфейса, нужен ли новый код вообще, или
достаточно проконтроллить типизацию и все?
проверка только для удобства только для удобства
соответствия типов
Ответь про DLL, как правильно экспортировать шаблон из DLL? Какие есть способы (мне на ум два приходят, например) чтобы избежать дублирования кода?
Нужны ли эти извращения в .NET?
Это вопросы не праздные как может показаться, после ответов на них (которые невозможно дать, не понимая как работает и то и другое) прояснится многое в том вопросе, который ты здесь пытаешься поднять.
Что ты подразумеваешь под "инстанцированием во время выполнения"?
Под "инстанцированием во время компиляции" я подразумеваю запись компилятором C# в выходную сборку обращений к конкретным методам/типам. То есть в IL вызов void List<string>.Add(string) уже будет отличаться от вызова void List<int>.Add(int).
using System.Collections.Generic;
using System;
using System.Reflection;
using System.Linq;
namespace CsPlay
{
class CsPlay
{
static void Main(string[] args)
{
var intList = new List<int>
var stringList = new List<string>
intList.Add(1);
stringList.Add("str");
intList.Add(2);
ShowInfo;
}
const byte callvirt = 0x6F;
static void ShowInfo
{
var assembly = Assembly.GetEntryAssembly;
var main = assembly.EntryPoint;
var body = main.GetMethodBody;
var il = body.GetILAsByteArray;
for (int i = 0; i < il.Length; i++)
if (il[i] == callvirt)
// выводим ссылку на метод
Console.WriteLine(BitConverter.ToInt32(il, i + 1;
Console.ReadKey;
}
}
}
в IL вызов void List<string>.Add(string) уже будет отличаться от вызова void List<int>.Add(int).Ну а как ты хотел? Естественно, запись в IL будет различаться. НО. Мне лично не очевидно _куда_ эти ссылки указывают. Ты утверждаешь, что в файле на диске, в сборке, где реализован List, будет код для List<int> и List<string>? Надеюсь, что нет. Тогда в файле твоей сборки есть эта реализация? Докажи, мне не очевидно.
Ты вот мне лучше ответь на то, что я выше написал. Ты лишь описываешь работу .NET, я же призываю включить твой аналитический аппарат и сравнить это с тем, что было в C++.
namespace TestDll
{
public class TestGen<T>
{
public void f
{
Console.WriteLine(" sucks");
}
}
}
В другой его юзаем:
namespace CsPlay
{
class Program
{
static void Main(string[] args)
{
var x = new TestDll.TestGen<int>
x.f;
}
}
}
Далее все компилим. Не запускаем (потому что и так ясно что будет выведено). Копируем для чистоты эксперимента в отдельную папку.
Далее изменяем только сборку DLL, сделав очевидное редактирование:
...
Console.WriteLine(" sucks gracefully");
...
Компилим, заменяем в нашей отдельной папке старую версию DLL на новую, запускаем на этот раз.
Если ты прав и generic инстанциируется на этапе компиляции как ты говоришь, то выведет, что я на подсосе, если же я прав, то...
Ты утверждаешь, что в файле на диске, в сборке, где реализован List, будет код для List<int> и List<string>? Надеюсь, что нет. Тогда в файле твоей сборки есть эта реализация? Докажи, мне не очевидно.если бы ты это делал, то ты бы как сделал?
если бы ты это делал, то ты бы как сделал?Если бы я реализовывал компилятор?
Есть спецификация языка, которая не позволяет на этапе компиляции инстанцировать generic'и конкретными типами.
Если бы я реализовывал компилятор?если бы ты реализовывал generic-и в .net
если бы ты реализовывал generic-и в .netНу вот я же написал, что спецификация требует возможности инстанцировать generic'и из чужой сборки и того, чтобы при изменении кода generic поведение менялось без перекомпиляции использующей его сборки. Этого невозможно добиться, если генерировать шаблонный код на стадии компиляции: если генерировать копии в сборке с generic'ом, то придется нагенерировать на все типы, что невозможно, да и как-то стремно =)
Если его генерировать в импортирующей сборке, то нарушается второе требование.
В итоге я бы сделал как и сделано: код генерируется во время работы JIT. Да и не факт, что генерируется (я там выше в табличке написал): пусть есть generic
class X<T> where T : IDisposable
{
public void f(T y)
{
y.Dispose;
}
}
зачем сдесь вообще копии кода? во всех случаях код f(T) будет следующим:
IDisposable)y).Dispose;
т.е. от компилятора просто требуется проконтроллировать, что у типа T по спецификации constraints в интерфейсе содержится метод Dispose.
Если же код примерно такой
class X<T> where T:struct
{
T a, b, c;
// ... whatever
}
то как бы этого ни не хотелось, придется генерировать код, так как размер типа T неизвестен и зависит от этого типа, соответственно для корректной работы методов generic'а X<T> требуется это знать. Но по приведенным мною выше причинам, генерировать этот код на этапе компиляции не удается.
Вот как-то так.
Я пока вон 'у задал вопрос по поводу "экспортирования" шаблонов из native-dll, пускай подумает, если не догадается, для тех, кто не знает, могу пояснить. Пусть пока сам ответит.
код генерируется во время работы JITа) работа JIT называется "компиляцией во время выполнения", что не противоречит ни твоему, ни моему утверждению
б) время работы ngen называется "предкомпиляцией" и происходит никак не во время выполнения, что не противоречит моему утверждению, но противоречит твоему
а) работа JIT называется "компиляцией во время выполнения", что не противоречит ни твоему, ни моему утверждениюА вот и неправда. Концептуально я прав: у тебя есть исходный код, он компилируется в MSIL. На этом этапе никакого инстанцирования не происходит. То что происходит дальше - вообще неинтересно, это все детали реализации Framework. Все что ты пишешь - это лишь отговорки.
б) время работы ngen называется "предкомпиляцией" и происходит никак не во время выполнения, что не противоречит моему утверждению, но противоречит твоему
То что ты называешь ngen "предкомпиляцией" и потом взываешь к словообразованию ("пред" значит "перед") и вовсе не грамотно, потому что он происходит уже после компиляции в MSIL. Т.е. это предJITирование на самом деле.
Что будет если я заюзаю ngen и потом изменю сборку с generic'ом?
В итоге я бы сделал как и сделано: код генерируется во время работы JIT.вот именно так оно и сделано.
в сборке одна копия, при инстанциировании в runtime-е JIT-компилятор для всех неvalue-типов генерит одну общую версия кода, а для каждого value-типа генерится своя версия.
А вот и неправда. Концептуально я прав: у тебя есть исходный код, он компилируется в MSIL. На этом этапе никакого инстанцирования не происходит. То что происходит дальше - вообще неинтересно, это все детали реализации Framework. Все что ты пишешь - это лишь отговорки.Всё, что ты пишешь - это лишь отговорки.
То что ты называешь ngen "предкомпиляцией" и потом взываешь к словообразованию ("пред" значит "перед") и вовсе не грамотно, потому что он происходит уже после компиляции в MSIL. Т.е. это предJITирование на самом деле."предJITирование"
Значит "предкомпиляция" - это словообразование? "Предкомпиляция" - это сокращение от "предварительная компиляция". После неё приведённой тобой программе не нужно никакого JIT'ирования. Разве что небольшие правки, да и то не факт.
Что будет если я заюзаю ngen и потом изменю сборку с generic'ом?
Вот это на самом деле довольно нетривиальный вопрос в том плане, что я не в курсе когда native image сборки может быть использован, а когда нет. Если у сборки строгое имя, и ты её версию при изменении не поменяешь, вполне может загрузиться вариант с u...nku sucks (лень проверять на самом деле). Если версию изменишь, а старую не удалить - точно вызовется u...nky sucks. Если удалить - скорее всего " sucks". А если имя нестрогое, то, вроде, её нельзя ngen'ом обработать.
UPD. То, что сначала было написано в первой части ответа слишком неполно отражало моё мнение, поэтому пришлось сократить.
Но мало того, что это сложно доказать, так ещё и не факт, что это истина.
Кстати да, концептуально ты был бы прав, если бы даже теоретически нельзя было бы реализовать такой JIT, который бы генерировал для того Vector'а код, сравнимый по производительности (или даже совпадающий) с аналогичным кодом на C++.Заметь, я ничего не говорил про мнение по поводу "предназначения" шаблонов и generics. Если хочешь знать мое мнение, то я скажу, что считаю, что конкретно в твоем случае проблема не в предназначении, а в том, что у "математических" классов в архитектуре нет общего интерфейса.
Но мало того, что это сложно доказать, так ещё и не факт, что это истина.
Мне не нравилось, что ты отождествляешь работу шаблонов и generics'ов. И ты до сих пор похоже не понял. Ответь все же на вопрос про экспортирование шаблонов из dll, тебе будет полезно, уверяю.
Значит "предкомпиляция" - это словообразование? "Предкомпиляция" - это сокращение от "предварительная компиляция".Задись, Витя, 3. Зачем оперировать терминами, в которых не смыслишь? пред в данном случае приставка, а не сокращение. Добавление приставки - это словообразование, называется приставочный метод (если правильно помню со школы).
Но это не главное. Ngen происходит _после_ компиляции в MSIL.
Всё, что ты пишешь - это лишь отговорки.Это я первый сказал =)
в сборке одна копия, при инстанциировании в runtime-е JIT-компилятор для всех неvalue-типов генерит одну общую версия кода, а для каждого value-типа генерится своя версия.стопудово так? т.е. ты знаешь, что так и есть? Тогда кульно, одобряю программистов Microsoft =)
Мне не нравилось, что ты отождествляешь работу шаблонов и generics'ов. И ты до сих пор похоже не понял. Ответь все же на вопрос про экспортирование шаблонов из dll, тебе будет полезно, уверяю.Это в твоих терминах я отождествляю работу шаблонов и generic'ов.
На твой простой вопрос я ответ знаю, C++ не может экспортировать шаблонную функцию из dll.
Но это не главное. Ngen происходит _после_ компиляции в MSIL.Но ведь ни как не во время исполнения, верно?
- НА ЭТАПЕ КОМПИЛЯЦИИ ТЫ ЕГО ПРОВОДИШЬ?В твоём вопросе ведь ни слова не было сказано про MSIL. Вот и я говорил не столько про MSIL, сколько про JIT и Ngen. И да, я в этом ответе исключил вариант с интерпретатором.
- ДА.
На твой простой вопрос я ответ знаю, C++ не может экспортировать шаблонную функцию из dll.Ну ладно, о функциях разговор не идет, но это опять же не главное, хотя с функциями куда проще.
Если задать вопрос "верно ли утверждение из цитаты?", то правильным ответом будет "и да и нет".
Вот есть stl, там что, нету шаблонных функций?
Да и шаблонных классов там навалом. Знаешь как работает?
В твоём вопросе ведь ни слова не было сказано про MSIL. Вот и я говорил не столько про MSIL, сколько про JIT и Ngen. И да, я в этом ответе исключил вариант с интерпретатором.что ты интерпретатор-то свой приплетаешь? Если нет этапа компиляции, то твой ответ "ДА" вообще абсурден. Это раз.
JIT - это уже runtime, как ни крути. Это часть Framework, а не C# compiler.
Это я первый сказал =)Поздравляю! В ход пошли весомые аргументы!
Вообще мне уже давно кажется, что с пониманием того, как всё работает, ни у кого из нас проблем нет. Возможно у кого-то есть проблемы с применением терминологии, но мне лично на них класть в данном случае.
Вот есть stl, там что, нету шаблонных функций?STL - текст, а не набор разделяемых динамически подгружаемых библиотек.
Да и шаблонных классов там навалом. Знаешь как работает?
Конечно, я знаю как он работает. Ещё с 8 или 9-ого класса школы. И как работают generic'и, с момента их появления примерно.
оздравляю! В ход пошли весомые аргументы!Вот тут тебя поздравить в пору, друг мой. Это ты как раз так ответил на мои слова (т.е. дословно повторил) =)
Ещё с 8 или 9-ого класса школы.Ой, я-то думал ты на первом курсе программировать начал. Значит ты вообще тяжелый случай.
JIT - это уже runtime, как ни крути. Это часть Framework, а не C# compiler.Я уже писал, что не спорю, что JIT - это runtime. Но почему ты так настойчиво игнорируешь Ngen?
Вот тут тебя поздравить в пору, друг мой. Это ты как раз так ответил на мои слова (т.е. дословно повторил) =)Передразнивание.
что ты интерпретатор-то свой приплетаешь? Если нет этапа компиляции, то твой ответ "ДА" вообще абсурден. Это раз.Про интерпретатор я как раз написал, чтобы ты случайно не подумал, что я его существование учитывал при ответе, и не стал рассматривать этот случай как аргумент против этого ответа.
Я уже писал, что не спорю, что JIT - это runtime. Но почему ты так настойчиво игнорируешь Ngen?зачем вообще отдельно рассматривать ngen?
ngen - это фактически тот же самый JIT, только выполняемый по требованию, а не по запуску.
стопудово так? т.е. ты знаешь, что так и есть? Тогда кульно, одобряю программистов Microsoft =)да, оно так и сделано.
Затем, что ngen делается не во время выполнения, а я пытаюсь опровергнуть утверждение, что инстанцирование всегда делается только во время выполнения.
Затем, что ngen делается не во время выполнения.и? и что в этом интересного? что такого интересного, что это необходимо разбирать как отдельный случай?
STL - текст, а не набор разделяемых динамически подгружаемых библиотек.Да, полуркал, так и есть. Все же я был об STL лучшего мнения.
Ладно, не суть. Я хотел услышать примерное это: в буквальном смысле экспортировать шаблоны из DLL невозможно. Обычно если есть небольшой шаблонный класс, то он просто помещается в h-файлы, сопровождающие DLL и инстанцируется в исользующем его модуле. Но чтобы сэкономить код/скрыть реализацию шаблона внутри DLL можно использовать несколько подходов.
Например вынести независящую от типа реализацию в базовый класс, от которого наследовать (private) шаблонные реализации со строгой типизацией. При этом шаблонный класс состоит только из небольших inline-методов. Хорошая рекомендация, чтобы в таком классе присутствовали только inline-методы.
поправил пост.
а я пытаюсь опровергнуть утверждение, что инстанцирование всегда делается только во время выполнения.проще считать, что ngen - это и есть во время выполнения.
Передразнивание.Вот я и говорю, что это я как раз и обратил внимание на твои методы спора, а ты продолжил, вместо того, чтобы привести аргументацию нормальную.
Ох как выкаблучился-то! Жаль мой ответ на твой вопрос уже был исчерпывающим, а то, что ты тут написал никакого отношения к теме не имеет.
я пытаюсь опровергнуть утверждение, что инстанцирование всегда делается только во время выполнения.Э-не-неее! Ты пытаешься утверждать следующее
UPD. Кстати, когда, если не на этапе компиляции, происходит собственно подстановка параметров в generic'и?или вот
- НА ЭТАПЕ КОМПИЛЯЦИИ ТЫ ЕГО ПРОВОДИШЬ?по крайней мере пытался. Но я уже вижу попытки вывернуться на вариант "не всегда", т.е. ты уже начинаешь понимать. В принципе я доволен.
- ДА.
Ох как выкаблучился-то! Жаль мой ответ на твой вопрос уже был исчерпывающим, а то, что ты тут написал никакого отношения к теме не имеет.Нет, ответа ты не дал даже близко просто потому что не мог (не знаешь попросту и узнавать лень). Просто я решил дать тебе пример чтобы подтолкнуть к мысли (да, пример оказался неудачным но все же есть либы, "экспортирующие" шаблоны.
проще считать, что ngen - это и есть во время выполнения.ngen задуман для двух целей, чтобы не быть "во время выполнения" и чтобы применять более сложные оптимизации (что впрочем, сводится всё к тому же "не во время выполнения", потому что во время выполнения - долго).
ngen задуман для двух целей, чтобы не быть "во время выполнения" и чтобы применять более сложные оптимизации (что впрочем, сводится всё к тому же "не во время выполнения", потому что во время выполнения - долго).Ладно давай проще. Ngen _точно_ не во время компиляции. Потому что вот я откомпилился и не знаю, будут меня Ngen-ить или нет. Так что при всех возможных пониманиях ты неправ.
по крайней мере пытался. Но я уже вижу попытки вывернуться на вариант "не всегда", т.е. ты уже начинаешь понимать. В принципе я доволен.[censored] Я тебе ещё на первой странице написал, что мы с тобой по-разному воспринимаем фразу "generics инстанцируются во время компиляции".
Попыток вывернуться я никаких не делаю. Перед тем, как отвечать "ДА", я сидел и думал, как в этот ответ вложить и ngen, и JIT, и интерпретатор, и в итоге решил, что если забить на случай с интерпретатором, то можно ответить "ДА" без зазрения совести, что я и сделал. Заметь, к разговору о интерпретаторах я вернулся сам и сам же тебе сказал, что намеренно не учитывал их существование в этом "ДА", а вовсе не ты меня отправил на это поле.
Тебе стоило довериться моему посту
но ты с тех пор слишком много стебался, сарказмировал и местами старался меня унизить, из-за чего моё положительное мнение о тебе, сложившееся из других постов развеялось в пух и прах.generics инстанциируются во время компиляцииОчевидно, мы с тобой по-разному воспринимаем эту фразу.
Впрочем, если ты согласишься признать, что моё понимание находилось на должном уровне и ничего нового для меня ты не утвреждал (ещё раз оговорюсь, с точностью до нашего понимания терминов я готов тебе всё это простить.
Ngen _точно_ не во время компиляции.Ох.
Ngen - компилятор из MSIL + metadata в native, равно как и JIT.- НА ЭТАПЕ КОМПИЛЯЦИИ ТЫ ЕГО ПРОВОДИШЬ?В твоём вопросе ведь ни слова не было сказано про MSIL. Вот и я говорил не столько про MSIL, сколько про JIT и Ngen.
- ДА.
Задорный спор ни о чем. Если кто забыл, после аббревиатуры JIT должно стоять еще одно слово. Напомнить, какое?
в .net-е есть следующие термины
компиляция в IL - она же компиляция в байт-код
компиляция в машкод - она же компиляция из байт-кода в машкод - она же native-компиляция
JIT-компиляция - это компиляция в машкод на лету во время передачи управления на .net-код
ngen-компиляция - компиляция в машкод по требованию предварительно
компиляция(просто) - если нет никаких оговорок, то под этим понимается "компиляция в IL"
на уровне компиляция - это во время "компиляции в IL"
во время выполнения - это во время "компиляции в машкод" (т.е. включая в себя в том числе и ngen)
generic инстанцируется - такой термин в целом не употребляется, поэтому что именно под этим подразумевается непонятно.
есть скорее термин параметризованный generic - это generic с подставленными типами
ps
соответственно фразу "generics инстанциируются во время компиляции" можно понимать по всякому, если учесть что никто не знает, что такое generic инстанциируется.
если ты согласишься признать, что моё понимание находилось на должном уровнене соглашусь, но важно ли это?
Ты пытаешься оправдать свои слова, не более, не менее.
Оправдание засчитываю, естественно. Исходное же утверждение неверно.
generic инстанцируется - такой термин в целом не употребляется, поэтому что именно под этим подразумевается непонятно.Согласен. Но там разговор шел о проведении аналогий между C++ шаблонами и .NET generics. Вот именно на различие этих двух сущностей я и указывал. Читать мой предыдущий пост, попыткам оправдаться я помешать не могу, но все же это увод разговора в русло определений и переливания из пустого в порожнее, я же пытался вывести топикстартера на дорогу честного сравнения двух механизмов. Он против. Почему сразу в этом не признаться - не знаю.
есть скорее термин параметризованный generic - это generic с подставленными типами
во время выполнения - это во время "компиляции в машкод" (т.е. включая в себя в том числе и ngen)Я вот тут читал-читал, но как-то не вмешивался, так как сам больше по Java, а .Net знаю постольку-поскольку... Но вот эта фраза, которую я процитировал, мне почему-то кажется немного спорной, так как она исключает из "времени выполнения" собственно время выполнения программы
А если по существу, то можно привести такой пример.
Вопрос: В программах на языке C когда происходит отождествление функций (то есть устанавливается соответствие кода, вызывающего функцию, конкретному телу функции, которые будет выполнено)?
Ответ: Во время компиляции, разумеется!
Этот ответ является с одной стороны христоматийным, а с другой стороны неверным, если принять терминологию некоторых участников этой дискуссии. Отождествление функций в программах написанных на C в большинстве современных систем может выполняеться (и как правило выполняется) в процессе запуска програмы при так называемой динамической сборке (связывании исполняемого файла с .so, .dll и т.п. файлами, содержащими тела библиотечных функций). Подсунув уже после компиляции новую версию .so, .dll и т.п. файла (что не только не запрещено, а даже, напротив, настоятельно рекомендуется с целью исправления ошибок и уязвимостей выявленных в прошлых версиях можно изменить тело функции, которое будет отождествлено с конкретным вызовом. Так что, ни о каком отождествлении во время компиляции речи не идёт...
Применительно к .Net, работу JIT и ngen (если я правильно понял что это можно считать оптимизацией интерпретации байт-кода (путём преобразования его в машинный код) и таким образом можно не отделять от собственно интерпретации. А вот стыковку сборок в работающее приложение (при которой, как я понял, выполняется генерация конкретных реализаций Genericов, описывающих Value-типы скорее похожа на динамичаскую сборку традиционного приложения из исполняемого файла и всяких .so и .dll (сборки, они даже внешне похожи на .dll и таким образом это скорее link-time. Так как link-timeа у нас для участников дискуссии, похоже, не существует, то можно приравнять его к compile-time.
"времени выполнения" собственно время выполнения программыда, можно дополнить, что
во время выполнения - это во время "компиляции в машкод" (т.е. включая в себя в том числе и ngen) + во время непосредственного выполнения программы
Вопрос: В программах на языке C когда происходит отождествление функций (то есть устанавливается соответствие кода, вызывающего функцию, конкретному телу функции, которые будет выполнено)?правильный ответ, получается:
Ответ: Во время компиляции, разумеется!
для статически слинкованных - во время компиляции,
для динамически слинкованных - предварительное во время компиляции(проверяется что сигнатура верная, что такое тело вообще где-то определено и т.д. а окончательное во время выполнения (точнее, во время выполнения, но до непосредственного выполнения)
Так как link-timeа у нас для участников дискуссии, похоже, не существует, то можно приравнять его к compile-time.link-time - это время выполнения, а не compile-time.
почему именно так? потому что важный водораздел между компиляцией и выполнением следующий:
компиляция - это то, что происходит на стороне разработчика,
время выполнения - это то, что происходит на стороне пользователя.
а окончательное во время выполнения (точнее, во время выполнения, но до непосредственного выполнения)Тут можно прикопаться, что есть DLL delay-loading =)
Тут можно прикопаться, что есть DLL delay-loadingесть такое, но это уже явная подгрузка, а не динамическая линковка.
есть такое, но это уже явная подгрузка, а не динамическая линковка.Опасные вещи говоришь. По-твоему LoadLibraryEx - это не динамическая линковка?
Хотя понимаю, что ты имел в виду. Ты как раз и решил, что я говорю о LoadLibraryEx в чистом виде. Есть именно delay loading, там всем этим линковщик и загрузчик занимаются автоматически.
По-твоему LoadLibraryEx - это не динамическая линковка?нет.
где в этом именно линковка?
ps
определение сходу
линковка - это автоматическое сопоставление имен функций их реальному телу
Я говорил не о runtime загрузке DLL, а об отложенной (delay-loading там именно линковка, соответствующая секция в PE есть, загрузчик это обрабатывает, при вызове функции из кода загружает нужную библиотеку при помощи LoadLibrary. Что не так опять?
а об отложенной (delay-loading там именно линковка, соответствующая секция в PE есть, загрузчик это обрабатывает, при вызове функции из кода загружает нужную библиотеку при помощи LoadLibrary. Что не так опять?стоп
ты о стандартной динамической-линковке? или о какой-то другой?
стандартная динамическая линковка делается именно до непосредственно выполнения, и если хоть одной либы нет, то программа вообще запускаться не будет.
ты о стандартной динамической-линковке? или о какой-то другой?http://www.codeproject.com/KB/DLL/Delay_Loading_Dll.aspx
Неужели так незаметны слова "delay loading"?
Неужели так незаметны слова "delay loading"?О! не знал о такой технике. Спасибо.
твое замечание принимается
для динамически слинкованных - предварительное во время компиляции(проверяется что сигнатура верная, что такое тело вообще где-то определено и т.д.)Лол, нет. Ни для программ на языке си, ни даже для программ на языке сепплес это неверно.
Алсо, может кто-нибудь объяснить мне суть дискуссии? Шарповые генерики устроены так, чтобы их можно было безопасно (с точки зрения типизации) инстанцировать в рантайме. То есть невозможно написать генерик, который при попытке инстанцирования кинет эксепшен.
Разница между "можно" и "обязательно", надеюсь, понятна? И, шире, между контрактом (описанным в терминах "всё должно работать, как если бы CLR вёл себя так: ...") и имплементацией, с точки зрения доступных оптимизаций? Кстати когда-то читал, а может даже и проверял, не помню, что JIT компиляция происходит даже не при линковке (динамической, естественно а при непосредственном использовании, то есть неиспользованные классы (а может и отдельные функции) не будут скомпилированы в нейтив код. Никто не мешает джиттеру порождать по одному реальному, оптимизированному (т.е. с прямыми вызовами, без дополнительных кастов и прочего оверхеда) нейтив классу на каждую инстанциацию генерика с данным набором параметров и он это даже точно делает для инстанциаций над value-types.
Разговор ведь начался именно со сравнительной эффективности плюсовых темплейтов и генериков, я правильно понял? Ну и о чём он тогда? Неэффективность состоит в однократном вызове джиттера в рантайме? ОМГ. Алсо, хочу заметить, что существование плюсов крайне мерзостным образом исказило представление о стоимости компиляции в мозгу среднестатистического быдлокодера.
Разговор ведь начался именно со сравнительной эффективности плюсовых темплейтов и генериков, я правильно понял?Неправильно, к сожалению.
Ну и о чём он тогда?Длинная история. Лично меня поражало дилетанство одного индивида и я не мог остановиться =)
Кстати когда-то читал, а может даже и проверял, не помню, что JIT компиляция происходит даже не при линковке (динамической, естественно а при непосредственном использовании, то есть неиспользованные классы (а может и отдельные функции) не будут скомпилированы в нейтив код.Так и есть, Just in Time — имеется в виду непосредственно при вызове.
Один момент в твоей речи подозрителен
Никто не мешает джиттеру порождать по одному реальному, оптимизированному (т.е. с прямыми вызовами, без дополнительных кастов и прочего оверхеда)какой оверхед несет каст? Можно даже учесть, что в .net и множественного наследования-то нет, а значит касты между ссылками на классы даже операции сложения не включают. Т.е. каст - это NOP, ни более, ни менее. // upd: конечно менее, это вообще пустота в маш. коде.
Это для reference types, для value types же есть и более веские причины делать инстанцирование (т.е отдельный код для каждого экземпляра я об этом говорил выше.
невозможно написать генерик, который при попытке инстанцирования кинет эксепшен.ты и правда так думаешь?
какой оверхед несет каст?Ну это как бы сравнительная языкология. Жавовские генерики проходят через type erasure, следовательно в них появляются рантаймовые ассерты на предмет того, что переданный параметр действительно имеет нужный тип.
Я про то, что если ты делаешь генерик вида void DoSomething<T>(T something) where T : ISomething, вовсе не обязательно, что в рантайме ты получишь динамический диспатч через интерфейс. Рантайм тебе гарантирует что в плане эксепшенов и прочего он будет вести себя так, как если бы ты написал void DoSomething(ISomething something но это как бы контракт, а не реализация. На практике же если ты ему передашь value type, то все вызовы пойдут напрямую, например. Для вызовов невиртуальных методов референс тайпов должно быть так же, по идее.
| | невозможно написать генерик, который при попытке инстанцирования кинет эксепшен.
| ты и правда так думаешь?
Prove me wrong.
| | невозможно написать генерик, который при попытке инстанцирования кинет эксепшен.Да тут наверное я тебя не так понял, если написать прямо в коде GenType<SomeType>, то исключения не последует, пожалуй =) Меня на Reflection опять понесло. Сообщение не стал удалять, ибо тупо =)
| ты и правда так думаешь?
Prove me wrong.
Я про то, что если ты делаешь генерик вида void DoSomething<T>(T something) where T : ISomething, вовсе не обязательно, что в рантайме ты получишь динамический диспатч через интерфейс. Рантайм тебе гарантирует что в плане эксепшенов и прочего он будет вести себя так, как если бы ты написал void DoSomething(ISomething something но это как бы контракт, а не реализация. На практике же если ты ему передашь value type, то все вызовы пойдут напрямую, например.У тебя какой-то странный взгляд на это. Конкретно в этом абзаце ты высказываешь какое-то свое видение вопроса. Типа должно быть тааак, на практике тааак. Есть, извините меня, спецификация языка, там все по полочкам: как должно быть в теории и на практике он соблюдается.
Для вызовов невиртуальных методов референс тайпов должно быть так же, по идее.Как так же? Если ты хочешь сказать, что он будет вызывать функцию из типа передаваемого параметра вместо того, чтобы полезть через интерфейс, указанный в constraints, и достать функцию базового класса, то ты ошибаешься.
Читай спеки@пиши верные высказывания
То есть невозможно написать генерик, который при попытке инстанцирования кинет эксепшен.если инстанциировать через reflection - то запросто, о чем уже и шла речь в треде
да, и вот такой generic (или его чуть усложненная модификация) падает в runtime
class My<TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10>
{
My<TItem2, TItem1, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10> item1;
My<TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, Item1> item1;
}
void Main
{
My<int, bool, short, long, char, byte, uint, ulong, float, double> item;
}
Никто не мешает джиттеру порождать по одному реальному, оптимизированномуно так сейчас не делается, если не считать value-типов
да, и вот такой generic (или его чуть усложненная модификация) падает в runtimeУх, как страшно жить =)
да, и вот такой generic (или его чуть усложненная модификация) падает в runtimeКстати, у меня не падает (после исправления двух опечаток). Какая версия студии у тебя?
Кстати, у меня не падает (после исправления двух опечаток). Какая версия студии у тебя?значит перемешивание типов в параметрах не полное, должно получаться 10! инстанциированных generic-ов
может конечно 10! мало, и надо сделать 12!-15!
значит перемешивание плохое, должно получаться 10! инстанциированных generic-овКруто. Ладно, скажи хоть что за эксепшен, любопытно.
может конечно 10! мало, и надо сделать 12!-15!
перемешивание типов в параметрах не полноеДа странно, вроде идея правильная, транспозиций соседних элементов и циклического сдвига должно хватить на все: то что транспозиций достаточно это очевидно, а любую транспозицию можно получить сопряжением одной любой со сдвигом.
был какой-то изящный пример, но сейчас не могу вспомнить.
неизящный следующий (см. ниже)
с классами отрабатывает нормально, а со структурами молча сразу выходит без всяких исключений - только в errorlevel выставляется код -2147023895 вместо 0
class My<TItem1, TItem2, TItem3, TItem4, TItem5, TItem6>
{
public static readonly My<TItem2, TItem1, TItem3, TItem4, TItem5, TItem6> item1
= My<TItem2, TItem1, TItem3, TItem4, TItem5, TItem6>.Default;
public static readonly My<TItem2, TItem3, TItem4, TItem5, TItem6, TItem1> item2
= My<TItem2, TItem3, TItem4, TItem5, TItem6, TItem1>.Default;
public static readonly My<TItem1, TItem2, TItem3, TItem4, TItem5, TItem6> Default
= new My<TItem1, TItem2, TItem3, TItem4, TItem5, TItem6>
}
static class Program
{
static void Main
{
Console.WriteLine(My<string, object, Control, Application, Button, ProgressBar>.item1);
//Console.WriteLine(My<int, bool, short, long, char, byte>.item1);
Console.WriteLine("...");
return;
}
}
Очевидно, разработчики стандарта чётко разделяют время трансляции в машинно-зависимый код и время исполнения.
System.TypeLoadException is thrown if typeTok cannot be found. (This is typically detected when CIL is converted to native code rather than at runtime.)
Оставить комментарий
Serab
Ах, вон оно что. Понял теперь откуда твои проблемы.Да, про ТВОЮ реализацию массива как класса с форума ФДС тред я не забуду никогда, я тебя уверяю =)
Что конкретно тебе интересно, ты так и не написал, нужно просто что-то «крутое» и невъебное. Читай книжки, желательно не на русском языке.