Re[8]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 21.12.13 15:11
Оценка:
Здравствуйте, Jack128, Вы писали:

J>А такие типы между сборок должны шарится?


Обязательно. И в этот то проблема — такие типы нужно протаптывать в CLR, причем с изменением метаданных. Последний раз метаданные менялись в далеком 2004, так что ...
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[9]: C# 6.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.12.13 17:43
Оценка: :)
Здравствуйте, AndrewVK, Вы писали:

AVK>Пфф.

AVK>Нет.
AVK>Т4 тоже не позволяет.
AVK>Имеет.

Голословные заявления и утверждения в стиле КО меня не интересуют.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 22.12.13 14:22
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Голословные заявления заявления и утверждения в стиле КО меня не интересуют.


Т.е. ты опять прочел по диагонали и почти ничего не понял.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[9]: C# 6.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.12.13 17:08
Оценка: 7 (1)
Здравствуйте, AndrewVK, Вы писали:

J>>А такие типы между сборок должны шарится?


AVK>Обязательно. И в этот то проблема — такие типы нужно протаптывать в CLR, причем с изменением метаданных. Последний раз метаданные менялись в далеком 2004, так что ...


Это не верные утверждения.

"Шарить" ничего не надо, даже вредно. Нужно соглашение по которому фреймворк будет считать типы одинаковыми и позволять передавать один вместо другого.

В метаданных нужно всего лишь отразить факт того что тип рассматривается как структурно эквивалентный. Это можно сделать даже простым атрибутом.

Вот что должно измениться, так это поведение фремворка. Но тут проблем возникнуть не должно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: C# 6.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.12.13 17:11
Оценка: :)
Здравствуйте, AndrewVK, Вы писали:

AVK>Т.е. ты опять прочел по диагонали и почти ничего не понял.


Если тебе приятно считать себя умнее других — считай. Мне все равно.

Если же хочешь нормальной дискуссии, потрудись аргументировать свои утверждения. Я не мальчик на "нет" отвечать — "да", и т.п.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: C# 6.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.12.13 22:09
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Ну понятно, как обычно читаем по диагонали. Не розлин, а razor.


А ты это сразу не понял? Очевидная же описка.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: C# 6.0
От: Sinix  
Дата: 23.12.13 06:38
Оценка:
Здравствуйте, VladD2, Вы писали:

S>>С структурной эквивалентностью вылазят проблемы с рефлексией (начиная c type.AssemblyQualifiedName), сериализацией и с xml-комментариями.

VD>Эти смелые утверждения нужно как следует обосновать. Я вот никаких проблем не вижу.

Проблемы решаются и даже несколькими способами, но каждый из вариантов порождает новые. Для начала, что должен вывести:
// Assembly 1
/// <returns>
/// Тип 1
/// </returns>
public var F() // Кстати, а как передавать такой тип через параметры?
{
  return new { Name = "A", Age = 10 };
}

// Assembly 2
/// <returns>
/// Тип 2
/// </returns>
public var F2()
{
  return new { Name = "B", Age = 11 };
}

var a = F();
var t = a.GetType();
a = F2();
var t2 = a.GetType();

Console.WriteLine(t == t2);

?
Тут какой вариант не выбери — будут свои косяки.

Кстати, какую подсказку должна показывать студия при наведении на a — "Тип 1", или "Тип 2"?


S>>Решить можно, но я не уверен что затраты соответствуют выигрышу.

VD>Нет там никаких особых затрат. И дотнет уже поддерживает ограниченную структурную эквивалентность для комовских типов.
Если ничего не путаю, она сводится к динамичесмкому маппингу к заданному интерфейсу, т.е. это не совсем структурная эквивалентность.

VD>Проверка структурной эквивалентности типов производится в момент загрузки сборок/типов. Далее для нужд рефлексии и т.п. используем первый попавшийся тип, а остальные позволяет передавать там где ожидаются их структурные эквиваленты.


Ага, это один из вариантов. У него три проблемы:
1. Сразу идёт лесом сериализация, т.к. типы исходного и десериализованного значений могут отличаться.
2. Замедляется загрузка сборок из-за проверки на эквивалентность типов.
3. Непредсказуемо ломается биндинг и прочие методы, завязанные на рефлексию. Например, Attribute.IsDefined() — атрибут-то можно навесить только на один из типов. Или завязка на по полное имя типа/его guid. Причём упасть оно может не на тестах, а уже в продакшне, например, из-за изменившейся логики ngen.

S>>Если уж передавать тип за границы сборки, то лучше объявить его явно и не возиться с "добавили поле в результат метода в сборке А -> всё упало в B".

VD>Это физически невозможно. Будет "брильянтовая проблема". В одной библиотеке объявляем тип. Другой объявляем тот же тип. Что делать приложению которое хочет использовать обе библиотеки и этот тип?
Это будут два разных типа, поскольку они объявлены в разных библиотеках. И то, что они _сейчас_ совпадают вплоть до имён-типов полей не даёт никаких гарантий, что так будет и в будущем.

С явным описанием типов у нас может быть только одно место, где мы ломаем совместимость сборок — собственно, само описание типа. С структурной эквивалентностью мы расширяем его до любой публичной сигнатуры, возвращающей анонимный тип. Затраты на тестирование возрастают соответственно.

Такие вещи нестрашны для мелких проектов. Для энтерпрайза, где типовое требование "чтоб работало на произвольной версии и не падало после обновлений" оно не подходит.
Re[12]: C# 6.0
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.12.13 07:10
Оценка:
Здравствуйте, Sinix, Вы писали:

S>>>Решить можно, но я не уверен что затраты соответствуют выигрышу.

VD>>Нет там никаких особых затрат. И дотнет уже поддерживает ограниченную структурную эквивалентность для комовских типов.
S>Если ничего не путаю, она сводится к динамичесмкому маппингу к заданному интерфейсу, т.е. это не совсем структурная эквивалентность.
Да, речь о структурной эквивалентности типов.

VD>>Проверка структурной эквивалентности типов производится в момент загрузки сборок/типов. Далее для нужд рефлексии и т.п. используем первый попавшийся тип, а остальные позволяет передавать там где ожидаются их структурные эквиваленты.


S>Ага, это один из вариантов. У него три проблемы:

S>1. Сразу идёт лесом сериализация, т.к. типы исходного и десериализованного значений могут отличаться.
А разве анонимные типы сериализуются?
S>2. Замедляется загрузка сборок из-за проверки на эквивалентность типов.
Не думаю что значительно
S>3. Непредсказуемо ломается биндинг и прочие методы, завязанные на рефлексию. Например, Attribute.IsDefined() — атрибут-то можно навесить только на один из типов. Или завязка на по полное имя типа/его guid. Причём упасть оно может не на тестах, а уже в продакшне, например, из-за изменившейся логики ngen.
Даже не представляю, как вешать атрибуты на анонимные типы.
Re[13]: C# 6.0
От: Sinix  
Дата: 23.12.13 07:55
Оценка:
Здравствуйте, samius, Вы писали:

S>А разве анонимные типы сериализуются?

Зависит от сериализатора. Из штатных — JavaScriptSerializer умел кажется.
Сейчас это в принципе неважно, анонимные типы как правило не выходят за границы метода. Но если нужно превратить их в полноценно используемые типы — нужна и поддержка сериализации.

S>>2. Замедляется загрузка сборок из-за проверки на эквивалентность типов.

S>Не думаю что значительно
Напомню, исходный пойнт был "Нет там никаких особых затрат" В лучшем случае получается hash match с последующей проверкой типов с совпадающими хешами. Если анонимные типы вложенные — всё становится заметно веселее.

S>Даже не представляю, как вешать атрибуты на анонимные типы.

Полноценная структурная эквивалентность подразумевает, что типы могут быть и неанонимными. Если ограничивать только ими, то пользы от структурной эквивалентности мало. Например, как передавать анонимный тип в параметры метода? Прописывать сигнатуру?

Там дело не только в атрибутах — придётся искать проблемные места в TypeDescriptor, CustomReflectionContext, сериализаторах и т.д. и т.п.

И всё это из-за того, что пользователь ленится написать
class A { public int X; public string Y; }

?
Re[12]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 23.12.13 09:01
Оценка:
Здравствуйте, VladD2, Вы писали:

AVK>>Т.е. ты опять прочел по диагонали и почти ничего не понял.

VD>Если тебе приятно считать себя умнее других — считай.

А если нет?

VD>Если же хочешь нормальной дискуссии, потрудись аргументировать свои утверждения


Чтобы была нормальная дисскуссия собеседник, как минимум, должен читать твои сообщения.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[10]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 23.12.13 09:01
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А ты это сразу не понял? Очевидная же описка.


Ну раз описка, то можно тогда пояснить, каким образом разор:
1) Заточен на языковой сервис в IDE и компиляторе?
2) Почему хелперы и лейауты не являются средством декомпозиции?
3) Каким образом он помогает "получать метаинформацию о коде шарпа"?
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[14]: C# 6.0
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.12.13 10:00
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>Зависит от сериализатора. Из штатных — JavaScriptSerializer умел кажется.

S>Сейчас это в принципе неважно, анонимные типы как правило не выходят за границы метода. Но если нужно превратить их в полноценно используемые типы — нужна и поддержка сериализации.
Если бы это было справедливо для всех типов, покидающих границы метода, то я бы согласился с тем что это было бы обязательной фичей.

S>Напомню, исходный пойнт был "Нет там никаких особых затрат" В лучшем случае получается hash match с последующей проверкой типов с совпадающими хешами. Если анонимные типы вложенные — всё становится заметно веселее.

Мне кажется что нас совершенно не должна беспокоить вложенность анонимных типов. Можно их все считать никуда не вложенными.

S>>Даже не представляю, как вешать атрибуты на анонимные типы.

S>Полноценная структурная эквивалентность подразумевает, что типы могут быть и неанонимными. Если ограничивать только ими, то пользы от структурной эквивалентности мало. Например, как передавать анонимный тип в параметры метода? Прописывать сигнатуру?
На сколько я понял, речь не идет о полноценной структурной эквивалентности всех типов в общем случае и анонимных и не анонимных типов в частности. Это поломает типизацию совершенно полностью. Этакий глобальный дак-тайпинг, где ни один метод не сможет гарантировать то что он принимает совершенно конкретный тип. Ему придется принимать все структурно-эквивалентное.
Потому уверен что обсуждается структурная эквивалентность только анонимных типов.

S>Там дело не только в атрибутах — придётся искать проблемные места в TypeDescriptor, CustomReflectionContext, сериализаторах и т.д. и т.п.

А это не про анонимные типы.
Re[15]: C# 6.0
От: Sinix  
Дата: 23.12.13 11:57
Оценка:
Здравствуйте, samius, Вы писали:

S>>Сейчас это в принципе неважно, анонимные типы как правило не выходят за границы метода. Но если нужно превратить их в полноценно используемые типы — нужна и поддержка сериализации.

S>Если бы это было справедливо для всех типов, покидающих границы метода, то я бы согласился с тем что это было бы обязательной фичей.
Ок, сформулируем так:
* для обычных типов "добавить сериализацию" означает "добавить сериализацию в объявление типа".
* для анонимных типов — "выкинуть нафиг и переписать на нормалььные типы".

Причём к "выкинуть нафиг" рано или поздно сводится почти всё, начиная с "добавить ещё одно поле к результату". Ну и зачем связываться?

S>>Напомню, исходный пойнт был "Нет там никаких особых затрат" В лучшем случае получается hash match с последующей проверкой типов с совпадающими хешами. Если анонимные типы вложенные — всё становится заметно веселее.

S>Мне кажется что нас совершенно не должна беспокоить вложенность анонимных типов. Можно их все считать никуда не вложенными.
Речь про вот это:
var y = new A
{
    X = new 
    {
        A = "123", B = 456
    },
    Y = new 
    {
        A = "789", B = 123
    },
    Z = Assembly2.NewAB("112", 453)
};


X, Y, Z должны быть признаны структурно эквивалентными. В ту же степь — финты вида
var MyMeth(int i)
{
    return i <= 0?
        null :
        new
        {
            I = i,
            Next = MyMeth(i-1)
        };
}


S>На сколько я понял, речь не идет о полноценной структурной эквивалентности всех типов в общем случае и анонимных и не анонимных типов в частности. Это поломает типизацию совершенно полностью. Этакий глобальный дак-тайпинг, где ни один метод не сможет гарантировать то что он принимает совершенно конкретный тип. Ему придется принимать все структурно-эквивалентное.

S>Потому уверен что обсуждается структурная эквивалентность только анонимных типов.
Тогда совсем неинтересно. Первая же проблема: как инстанс анонимного типа передать через параметр?

S>>Там дело не только в атрибутах — придётся искать проблемные места в TypeDescriptor, CustomReflectionContext, сериализаторах и т.д. и т.п.

S>А это не про анонимные типы.
Про них. Потому что у нас всё вышеперечисленное может работать с анонимными типами. И ждать косяков от
var x = new { A = 123 };
dynamic y = x;
WriteLine(y.A);

или от
var x = new { A = 123 };
x.GetType().Assembly;

только потому, что у нас подгрузилась другая сборка с структурно эквивалентным типом и при разрешении CallSite полезли неочевидности, не хочется ну вот совсем.

Конечно, есть альтернативный вариант: для всех структурно эквивалентных анонимных типов в рантайме генерится анонимный тип, прописанный в mscorlib, но там тоже есть свои неоднозначности.
Ну и VladD2 предложил именно вариант с подменой на первый попавшийся совместимый тип — его и обсуждаем пока.
Re[13]: C# 6.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.12.13 12:04
Оценка: -1 :)
Здравствуйте, AndrewVK, Вы писали:

AVK>Чтобы была нормальная дисскуссия собеседник, как минимум, должен читать твои сообщения.


Кажись понял о чем ты. Сори, действительно, попутал. Но можно было бы не выпендриваться, а сразу сказать.

Что до Разор вс. Т4, то это замена шыла на мыло.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 23.12.13 12:39
Оценка: +2
Здравствуйте, VladD2, Вы писали:

VD>Но можно было бы не выпендриваться, а сразу сказать.


Ты, видимо, о чем то о своем, а не про razor.
...
Не розлин, а razor.


VD>Что до Разор вс. Т4, то это замена шыла на мыло.


Если оставить за скобками жутко избыточный синтаксис Т4, то может быть. Но если не шашечки а ехать, то разор сильно удобнее.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[16]: C# 6.0
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.12.13 12:42
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>>Сейчас это в принципе неважно, анонимные типы как правило не выходят за границы метода. Но если нужно превратить их в полноценно используемые типы — нужна и поддержка сериализации.

S>>Если бы это было справедливо для всех типов, покидающих границы метода, то я бы согласился с тем что это было бы обязательной фичей.
S>Ок, сформулируем так:
S>* для обычных типов "добавить сериализацию" означает "добавить сериализацию в объявление типа".
S>* для анонимных типов — "выкинуть нафиг и переписать на нормалььные типы".
Да, думаю что это приемлемо.

S>Причём к "выкинуть нафиг" рано или поздно сводится почти всё, начиная с "добавить ещё одно поле к результату". Ну и зачем связываться?

не понял. Для того что бы добавить еще одно или 10 полей к результату, выкидывать не надо.
А связываемся мы с этим затем, что бы мы могли делать объявления методов, совместимые с анонимными типами. Linq-у это здорово поможет.

S>>Мне кажется что нас совершенно не должна беспокоить вложенность анонимных типов. Можно их все считать никуда не вложенными.

S>Речь про вот это:
S>
S>var y = new A
S>{
S>    X = new 
S>    {
S>        A = "123", B = 456
S>    },
S>    Y = new 
S>    {
S>        A = "789", B = 123
S>    },
S>    Z = Assembly2.NewAB("112", 453)
S>};
S>

Я не вижу здесь причин для того что бы делать типы вложенными.

S>X, Y, Z должны быть признаны структурно эквивалентными. В ту же степь — финты вида

S>
S>var MyMeth(int i)
S>{
S>    return i <= 0?
S>        null :
S>        new
S>        {
S>            I = i,
S>            Next = MyMeth(i-1)
S>        };
S>}
S>

И тут тоже

S>>Потому уверен что обсуждается структурная эквивалентность только анонимных типов.

S>Тогда совсем неинтересно. Первая же проблема: как инстанс анонимного типа передать через параметр?
Не вижу проблемы. Объявляем параметр примерно так
void Foo({ A:string, B: int} value);
и передаем. Все что имеет совместимый тип должно передаваться без вопросов. Неочевидным будет лишь value.GetType().

S>>А это не про анонимные типы.

S>Про них. Потому что у нас всё вышеперечисленное может работать с анонимными типами. И ждать косяков от
S>
S>var x = new { A = 123 };
S>dynamic y = x;
S>WriteLine(y.A);
S>

Это ведь уже как-то работает с анонимными типами?
S> или от
S>
S>var x = new { A = 123 };
S>x.GetType().Assembly;
S>

Тут неоднозначность раньше возникает. Уже GetType() вернет неизвестно что.
S>только потому, что у нас подгрузилась другая сборка с структурно эквивалентным типом и при разрешении CallSite полезли неочевидности, не хочется ну вот совсем.
Верно, не хочется.
S>Конечно, есть альтернативный вариант: для всех структурно эквивалентных анонимных типов в рантайме генерится анонимный тип, прописанный в mscorlib, но там тоже есть свои неоднозначности.
S>Ну и VladD2 предложил именно вариант с подменой на первый попавшийся совместимый тип — его и обсуждаем пока.
Можно обсудить и другие варианты. Например, генерацию кода для конвертации совместимых типов вместо их подмены рантаймом.
Re[15]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 23.12.13 13:24
Оценка:
Здравствуйте, samius, Вы писали:

S>Потому уверен что обсуждается структурная эквивалентность только анонимных типов.


Влад, имхо, как раз таки обсуждает
Автор: VladD2
Дата: 22.12.13
именно глобальную эквивалентность.

S>>Там дело не только в атрибутах — придётся искать проблемные места в TypeDescriptor, CustomReflectionContext, сериализаторах и т.д. и т.п.

S>А это не про анонимные типы.

Если есть хитрый тип, то его можно будет передать туда, где используется стандартная компонентная модель (их, кстати, несколько). А значит надо, как минимум, понять что при этом получится.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[17]: C# 6.0
От: Sinix  
Дата: 23.12.13 13:53
Оценка:
Здравствуйте, samius, Вы писали:

S>>Причём к "выкинуть нафиг" рано или поздно сводится почти всё, начиная с "добавить ещё одно поле к результату". Ну и зачем связываться?

S>не понял. Для того что бы добавить еще одно или 10 полей к результату, выкидывать не надо.
Надо. Т.к. сборки пользователей завязаны на старую сигнатуру и их никто перекомпилировать после каждого сервис-пака не будет.

S>А связываемся мы с этим затем, что бы мы могли делать объявления методов, совместимые с анонимными типами. Linq-у это здорово поможет.

Не поможет. Добавляем всего-то
var a = 
  from y in x.Y
  from z in y.Z
  let a = new { A = y, B = z }
  group new { y, S = a } by a into g
  select SomeFunc(g.Key, g.First());

и
void Foo({ A:string, B: int} value);

превращается в "мамадорогая, зачем я с этим связался " Смысл анонимных типов — в отсутствии необходимости описывать тип. Как только мы описали тип — всё, можно его вытащить в явное описание и не страдать фигнёй.

Ну, или оставить как есть и проверять сигнатуры вручную при каждом мерже исправлений
Альтернативщину вида "пишем Foo(var a) — компилятор разрулит" лучше оставить языкам с рантайм-верификацией типов, для шарпа это всё-таки изврат

S>Я не вижу здесь причин для того что бы делать типы вложенными.

Проектирование мейнстримного ЯП должно осуществляться чуть по другим критериям Просто потому, что если дырка есть — её обязательно используют и она так и останется, чисто из соображений совместимости.

Навскидку — ApplicationException/SystemException, Delegate/MulticastDelegate, AppDomainSetup.ShadowCopyFiles = "True" (угу, строковая константа), ковариантные массивы, IEnumerator в виде структуры, delegate.BeginInvoke() и прочее-прочее так и остались с нами спустя 11 лет после выхода первого фреймворка (ёшкин кот, как время летит!).

Так что лучше не создавать себе проблем, чем потом геройски с ними бороться.


S>Объявляем параметр примерно так

S>void Foo({ A:string, B: int} value);
Оно будет работать только для совсем примитивных вариантов. Чуть посложнее — и мы завязнем в сверке сигнатур после каждой правки.

S>и передаем. Все что имеет совместимый тип должно передаваться без вопросов. Неочевидным будет лишь value.GetType().

А у мейнстрим-языка нет права на "всё ок, но тут неочевидным будет". Берём шанс получить ошибку (довольно высокий, учитывая средний уровень по палате), умножаем на количество пользователей — получаем дофигаллион потраченного времени и хороший плевок себе в карму как разработчику.


S>>>А это не про анонимные типы.

S>>Про них. Потому что у нас всё вышеперечисленное может работать с анонимными типами. И ждать косяков от
S>>
S>>var x = new { A = 123 };
S>>dynamic y = x;
S>>WriteLine(y.A);
S>>

S>Это ведь уже как-то работает с анонимными типами?
Да, но только потому, что у нас нет граблей с изменением CallSite от запуска к запуску. Грубо говоря, метод T<>anon.get_A не должен прыгать из сборки в сборку

S>> или от

var x = new { A = 123 };
x.GetType().Assembly;

S>Тут неоднозначность раньше возникает. Уже GetType() вернет неизвестно что.
Ага. Но пользователю от этого не легче

S>>Ну и VladD2 предложил именно вариант с подменой на первый попавшийся совместимый тип — его и обсуждаем пока.

S>Можно обсудить и другие варианты. Например, генерацию кода для конвертации совместимых типов вместо их подмены рантаймом.
А это уже реальнее. Тогда надо вводить явное приведение с ducktyping, аля
var x = y castas ISomeFeature; // y не реализует ISomeFeature, в x попадает обёртка с ссылкой на y, реализующая ISomeFeature

Минусы конечно будут, например — сложность с возвращением исходной ссылки на y, зная только x.
Как плюс — мы вообще освобождаемся от проблемы "как обозвать анонимный тип чтобы оставить его анонимным". Ну, и не надо трогать рантайм — всё можно сделать силами компилятора.
Re[12]: C# 6.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.12.13 01:38
Оценка: 39 (1)
Здравствуйте, Sinix, Вы писали:

S>Проблемы решаются и даже несколькими способами, но каждый из вариантов порождает новые. Для начала, что должен вывести:

S>?

Для начала нужно заметить, что вывод типов на глобальном уровне плохая идея. Она навредит интелисенсу.

Должно быть возможно определять такие типы явно. Нечто вроде:
using LacalNameForRecord = <string Name, int Age>;

public <string Name, int Age> F(<string Name, int Age> param) // через параметры как-то так, но это на практике не нужно
{
  return param;
}

public LacalNameForRecord F() // через параметры как-то так, но это на практике не нужно
{
  return new { Name="A", Age=42 };
}

Синтаксис не так важен. Важно только чтобы он был краток и не конфликтовал с теми местами где возможно объявление типа.

S>Тут какой вариант не выбери — будут свои косяки.


Что-то я их не улавливаю. Можно по подробнее?

S>Кстати, какую подсказку должна показывать студия при наведении на a — "Тип 1", или "Тип 2"?


Такую:

<string Name, int Age>

это структурные типы. Нечего думать о них как о наминативных.

S>Если ничего не путаю, она сводится к динамичесмкому маппингу к заданному интерфейсу, т.е. это не совсем структурная эквивалентность.


Здесь и нужно сделать динамическое отображение типов. Делать поддержку структурной типизации с нуля слишком объемная задача. Предлагаемого мной решения хватит за глаза.

VD>>Проверка структурной эквивалентности типов производится в момент загрузки сборок/типов. Далее для нужд рефлексии и т.п. используем первый попавшийся тип, а остальные позволяет передавать там где ожидаются их структурные эквиваленты.


S>Ага, это один из вариантов. У него три проблемы:

S>1. Сразу идёт лесом сериализация, т.к. типы исходного и десериализованного значений могут отличаться.

Еще раз, по буквам. Совместимость типов обеспечивает рантайм. Если у кого-то вдруг есть другой тип, он все равно должен эквивалентен исходному. Рантайм просто должен подменять ссылки при попытке их получения, или обеспечить эквивалентность путем переопределения виртуальных методов обжекта.

S>2. Замедляется загрузка сборок из-за проверки на эквивалентность типов.


Не стоит придумывать не существующих проблем. Это вопрос качества реализации. Потом тебя вот мало волнует то, что сейчас загрузка классов безбожно тормозит, а какие-то там сравнения токенов тебя вдруг так взволновали.

S>3. Непредсказуемо ломается биндинг и прочие методы, завязанные на рефлексию.


С чего бы это?

S>Например, Attribute.IsDefined() — атрибут-то можно навесить только на один из типов.


Ох, ох, ох... Эквивалентными могут быть только эквивалентные типы. Если у них различаются атрибуты, то выдаем ошибку компиляции дублируем ее исключением при загрузке в рантайме. Для проверки достаточно создать шифровальный хэш с типа и сравнивать их. Если есть разница — в лес.

S> Или завязка на по полное имя типа/его guid. Причём упасть оно может не на тестах, а уже в продакшне, например, из-за изменившейся логики ngen.


Не выдумывай проблем. А то эдак любую пургу можно обосновать.

S>Это будут два разных типа, поскольку они объявлены в разных библиотеках. И то, что они _сейчас_ совпадают вплоть до имён-типов полей не даёт никаких гарантий, что так будет и в будущем.


На то во фреймворк нужно встроить дополнительные проверки. Как я уже говорил выше, достаточно сварганить хэш и сравнивать его. У того же гита никаких проблем при сравнении целых репозиториев.

S>С явным описанием типов у нас может быть только одно место, где мы ломаем совместимость сборок — собственно, само описание типа. С структурной эквивалентностью мы расширяем его до любой публичной сигнатуры, возвращающей анонимный тип. Затраты на тестирование возрастают соответственно.


Расшифруй плиз свои мысли.
За одно подумай почему с сигнатурами функций нет тех же проблем и какая разница между ними и записями. Вот чем отличается изменение:
void Foo(int a, strind b);

на
void Foo(strind b, int a);

от
<int a, strind b> Foo();

на
<strind b? int a>  Foo();

?

Фиг бы даже с тем, что изменение публичного АПИ — это не очень дальновидное занятие. Но в чем же все таки отличие от методов? Я вижу только одно — перестановка именованных членов может вообще не вызвать проблем, так как обращение к ним по именам идет.

S>Такие вещи нестрашны для мелких проектов. Для энтерпрайза, где типовое требование "чтоб работало на произвольной версии и не падало после обновлений" оно не подходит.


Какая-то мантра. Меня интересуют исключительно технические подробности.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: C# 6.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.12.13 01:40
Оценка: -1
Здравствуйте, AndrewVK, Вы писали:

AVK>

AVK>Ты, видимо, о чем то о своем, а не про razor.
AVK>...
AVK>Не розлин, а razor.


Да, да. А до этого страница в стиле "да", "нет". Мне, после третьей строки, просто не захотелось на это тратить свое время.

VD>>Что до Разор вс. Т4, то это замена шыла на мыло.


AVK>Если оставить за скобками жутко избыточный синтаксис Т4, то может быть.


Не плохая идея. Тебя же не напрягает жудко избыточный синтаксис шарпа?

AVK>Но если не шашечки а ехать, то разор сильно удобнее.


Это ни шашечки, и не ехать. Это костыли. Ехать на них не выйдет. Так, ковылять потихонечку.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.