В качестве основной цели задекларированна поддержка функционального стиля. 1) Неявно типизированные локальные переменные (implicitly typed local variable). То о чем долго говорили большевики в форуме философия. Даже ключевое слово народ там угадал. Пример:
var i = 5;
var s = "Hello";
var d = 1.0;
var numbers = new int[] {1, 2, 3};
var orders = new Dictionary<int,Order>();
var x; // Error, no initializer to infer type fromvar y = {1, 2, 3}; // Error, collection initializer not permittedvar z = null; // Error, null type not permittedint[] numbers = { 1, 3, 5, 7, 9 };
foreach (var n in numbers) Console.WriteLine(n);
Зачем это нужно, надеюсь понятно.
2) Расширяющие методы (Extension methods). Хитрая штука. Позволяет объявлять статические методы с параметром this и привязывать их в качестве метода экземпляра к существующим классам.
Объявляются такие методы как обычные, но перед первым параметром добавляется модификатор this.
namespace Acme.Utilities
{
public static class Extensions
{
public static int ToInt32(this string s) {
return Int32.Parse(s);
}
public static T[] Slice<T>(this T[] source, int index, int count) {
if (index < 0 || count < 0 || source.Length – index < count)
throw new ArgumentException();
T[] result = new T[count];
Array.Copy(source, index, result, 0, count);
return result;
}
}
}
Использовать это очень просто — достаточно написать using на соотв. неймспейс.
using Acme.Utilities;
...
string s = "1234";
int i = s.ToInt32(); // Same as Extensions.ToInt32(s)int[] digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int[] a = digits.Slice(4, 3); // Same as Extensions.Slice(digits, 4, 3)
Сахар конечно, но забавно.
Обсуждается необходимость расширяющих свойств, событий и операторов, но пока такое не поддержвается.
3) Лямбда-выражения. Выражения, служащие для написания программ в функциональном стиле. Вобщем то в 2.0 анонимные методы очень на это похожи, но в 3.0 сделана попытка преобразовать внешний вид к более функциональному стилю. Для этого введен новый токен — =>.
Пример:
delegate R Func<A,R>(A arg);
...
Func<int,int> f1 = x => x + 1; // Ok
Func<int,double> f2 = x => x + 1; // Ok
Func<double,int> f3 = x => x + 1; // Error
Любители функционального стиля будут довольны. Хотя возможность творить на этой базе извраты (особенно если совместно с дженериками) меня пугает.
4) Инициализаторы объектов и коллекций (Object and collection initializers). Позволяют в одном выражении вызвать конструктор и присвоить ряд значений. Сахарок для улучшения читаемости кода.
Примеры:
var a = new Point { X = 0, Y = 1 };
// which has the same effect as
// var a = new Point();
// a.X = 0;
// a.Y = 1;var r = new Rectangle {
P1 = new Point { X = 0, Y = 1 },
P2 = new Point { X = 2, Y = 3 }
};
// which has the same effect as
// var r = new Rectangle();
// var __p1 = new Point();
// __p1.X = 0;
// __p1.Y = 1;
// r.P1 = __p1;
// var __p2 = new Point();
// __p2.X = 2;
// __p2.Y = 3;
// r.P2 = __p2;var contacts = new List<Contact> {
new Contact {
Name = "Chris Smith",
PhoneNumbers = { "206-555-0101", "425-882-8080" }
},
new Contact {
Name = "Bob Harris",
PhoneNumbers = { "650-555-0199" }
}
};
// which has the same effect as
// var contacts = new List<Contact>();
// var __c1 = new Contact();
// __c1.Name = "Chris Smith";
// __c1.PhoneNumbers.Add("206-555-0101");
// __c1.PhoneNumbers.Add("425-882-8080");
// contacts.Add(__c1);
// var __c2 = new Contact();
// __c2.Name = "Bob Harris";
// __c2.PhoneNumbers.Add("650-555-0199");
// contacts.Add(__c2);
Не уверен, но по идее должно работать и так:
var dict = new Dictionary<string, int> {
new KeyValuePair<string, int>("one", 1),
new KeyValuePair<string, int>("two", 2),
new KeyValuePair<string, int>("three", 3)
}
5. Анонимные типы. Проистекают из возможностей в п.1 и п.4. На основании объектного инициализатора выводится тип.
var p1 = new { Name = "Lawnmower", Price = 495.00 };
var p2 = new { Name = "Shovel", Price = 26.95 };
p1 = p2;
// Компилятор неявно создает следующий класс:
// class __Anonymous1
{
private string _name;
private double _price;
public string Name { get {return _name;} set {_name = value;}}
public double Price { get {return _price;} set {_price = value;}}
}
Прикольно. К сожалению, если я правильно понял, использовать такие типы без рефлекшена или делегатов можно только внутри одного метода.
6. Неявно типизированные массивы. Тоже сахарок, позволяющий не указыватьв new тип массива.
var a = new[] { 1, 10, 100, 1000 }; // int[]var b = new[] { 1, 1.5, 2, 2.5 }; // double[]var c = new[] { "hello", null, "world” }; // string[]
var d = new[] { 1, "one", 2, "two" }; // Error
7. Выражения запроса. (Query expressions). В новый язык добавлены декларативные конструкции, похожие на SQL.
Можно писать так:
from c in customers
where c.City == "London"from o in c.Orders
where o.OrderDate.Year == 2005
select new { c.Name, o.OrderID, o.Total }
Класс, для которого разрешены такие фокусы, должен выглядеть примерно так:
delegate R Func<A,R>(A arg);
class C<T>
{
public C<T> Where(Func<T,bool> predicate);
public C<S> Select<S>(Func<T,S> selector);
public C<S> SelectMany<S>(Func<T,C<S>> selector);
public O<T> OrderBy<K>(Func<T,K> keyExpr);
public O<T> OrderByDescending<K>(Func<T,K> keyExpr);
public C<G<K,T>> GroupBy<K>(Func<T,K> keyExpr);
public C<G<K,E>> GroupBy<K,E>(Func<T,K> keyExpr, Func<T,E> elemExpr);
}
class O<T> : C<T>
{
public O<T> ThenBy<K>(Func<T,K> keySelector);
public O<T> ThenByDescending<K>(Func<T,K> keySelector);
}
class G<K,T>
{
public K Key { get; }
public C<T> Group { get; }
}
ИМХО изврат редкостный. Насколько это будет полезно я пока ответить затрудняюсь.
8. Дерево выражений. Лямбда-выражения преобразуются компилятором в анонимные методы. Однако есть возможность сохранять эти самые выражения ввиде структуры с данными, которые умеют потом, в рантайме, при помощи эмита генерить эти самые методы:
Func<int,int> f = x => x + 1; // Code
Expression<Func<int,int>> e = x => x + 1; // Data
Зачем это нужно пока не сказано. Все что есть:
Expression trees are efficient in-memory data representations of lambda expressions and make the structure of the expression transparent and explicit.
Вот так — прозрачные и явные. Попой чую, что для каких то особо хитрых извратств в рантайме (скорее всего связанных с п.7), но чего то вечером пример придумать не могу. Ну разве что такую лямбду можно будет сериализовать (к примеру, чтобы сохранить в БД или передать по сети).
Здравствуйте, TK, Вы писали:
TK>Думаю, что за ~3000$ (стоимость участия с налогами) можно не только в TK>джинсах, а в чем угодно
Флеш-моб может устроить ? Всем россиянам, кто будет принимать участие — явиться в шапках-ушанках с бутылкой водки в кармане и с карманным медведем на поводке
Здравствуйте, _FRED_, Вы писали:
_FR>Гхм. Если не сложно, а что за история?
Поищи здесь и в философии поиском, совсем недавно была заметка о том, почему пришлось править рантайм в самый последний момент. Вкратце — проблема в боксинге. Т.е. в текущем варианте:
int? i = null;
Console.WriteLine(i == null); // Выводится True, что нормально.object o = i;
Console.WriteLine(o == null); // Выводится False, что, мягко говоря, не очень логично.
_FR>На PDC 2005 _FR>Вот, блин, дают Кто-нибудь бывает на таких мероприятиях?
Здесь страничка появилась "Visual C# Home > Future Versions". Среди прочего там лежит "csharp 3.0 specification.doc" — набросок новых фич в третьей версии.
А 22-го сентября будет чат с обсуждением C# 3.0 Language Enhancements, 1:00 — 2:00 P.M. Pacific time.
Здравствуйте, AndrewVK, Вы писали:
VD>>Вот нарыл как можно: VD>>var scoreRecordsDict = scoreRecords.ToDictionary(sr => sr.Name);
AVK>А как это работает? Рефлекшен?
По идее, можно и без рефлекшена:
using System;
using System.Collections.Generic;
public delegate R Func<A,R> (A arg);
public static class Extensions
{
public static Dictionary<K,T> ToDictionary<T,K>(this IEnumerable<T> collection, Func<T,K> func)
{
var dict = new Dictionary<K,T>();
foreach (T elem in collection)
dict.Add(func(elem), elem);
return dict;
}
}
public static class Program
{
public static void Main(string[] args)
{
var dict = (new [] {"aaa", "b", "cccc", "dd"}).ToDictionary(s => s.Length);
Console.WriteLine(dict[3]);
}
}
Здравствуйте, TK, Вы писали:
TK>Expression trees используются в DLinq для генерации SQL запросов. т.к. это позволяет разобрать выражение
Прежде чем рассуждать, лучше бы ссылочками покидался. А то еле еле нашел о чем ты говорил.
Спецификация на DLinq — здесь — query от C#3.0 на реляционные базы
Спецификация на XLinq — здесь — query от C#3.0 на xml
Здравствуйте, _FRED_, Вы писали:
_FR>А зачем они делегат Func (из System.Query) назвали сокращённо? Есть же прекрасное слово Function _FR>Надеюсь, поправят
Поправляю. Судя по всему ты не любишь Visual Basic. Там уже давно забили это слово под себя.
Hello, "_FRED_"
> Не... Не люблю тусовки, хотя по слухам к ним и в джинсах можно.. но за > инфу всё равно спасибо, мне казалось, что появиться на такой тусовке не > просто.
Думаю, что за ~3000$ (стоимость участия с налогами) можно не только в
джинсах, а в чем угодно
Posted via RSDN NNTP Server 1.9
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, AndrewVK, Вы писали:
AVK>7. Выражения запроса. (Query expressions). В новый язык добавлены декларативные конструкции, похожие на SQL. AVK>Можно писать так: AVK>
AVK>from c in customers
AVK>where c.City == "London"
AVK>from o in c.Orders
AVK>where o.OrderDate.Year == 2005
AVK>select new { c.Name, o.OrderID, o.Total }
AVK>
AVK>ИМХО изврат редкостный. Насколько это будет полезно я пока ответить затрудняюсь.
Учитывая, что работать это будет не только с базами данных, но и с любой коллекцией то, достаточно полезно.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
.
S> А также интересно, как там с конфликтами имен. S>Просто может появиться великолепная возможность придавать интерфейсам дефолтные реализации и утилитные методы. Примерно так: S>
S>public static string Concat(this IEnumerable self, string separator)
S>{
S> StringBuilder sb = new StringBuilder();
S> foreach(object o in self)
S> {
S> sb.Append(o);
S> sb.Append(separator);
S> }
S> if (sb.Length > 0)
S> sb.Length -= separator.Length;
S>}
S>
Да интерфейся это все фигня. Вот то что можно расширять запечатанные классы (такие как string), вот это вообще здорово!
S>И это даст возможность писать .Concat(";") для любого IEnumerable.
Ага. Только лучше не конкат, а ToString(";") или ToSeparatedString(";").
S>Для бизнес-объектов это великая штука. Вот были у нас объекты Customer. А теперь мы дописываем cборку Orders, и у Customer появляется коллекция .Orders.
Э... для не бизнес-объектов это тоже очень нужно. Ну, прикинь как здорово дописать к тем же IEnumerable<T> и T[] такие агреггирующие функции как Max(), Avg(), Select. Это в сочетании с запросами позволит работать со списками почти как на настоящем SQL-е.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Я тоже глянул. Не очень то специализированное. Обработка списков одна из самых часто встречающихся задач.
Вот именно что обработка! Здесь же только запрос в select-like стиле.
VD> К тому же это только сахар. Все переписывается в функциональный силь. Так что это встроенный DSL.
Ключевой момент DSL в том, что его можно менять под предметную область. А здесь ничего менять нельзя. Так что это нифига не DSL.
>А общее кол-во тусовщиков — несколько сотен или тыщ?
Несколько сотен это только у нас на DevDays. Думаю, что реально тысяч 7 участников. Может и больше.
Здравствуйте, _FRED_, Вы писали:
TK>>Думаю, что за ~3000$ (стоимость участия с налогами) можно не только в TK>>джинсах, а в чем угодно
_FR>Ну и налоги же у них! Вроде по ссылке $1000, если незнакомые мне слова ничего существенного не обозначают
1000$ это не для всех. Для остальных буклет из MSDN предлагает регистрацию за 2300 eur + 19% vat
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, AndrewVK, Вы писали:
AVK>1) Неявно типизированные локальные переменные (implicitly typed local variable). То о чем долго говорили большевики в форуме философия. Даже ключевое слово народ там угадал.
Ха! Большивики еще говорили о том, что разумно было бы ввести неизменяемые локальные переменне.
А вообще, МС как всегда реализует чужие идеи называя их своими инменами. Это дело в исходном виде называлось "вывод типов" (type inference).
Вот бы еще сделали бы выволд типов при инициализации массивов с автоматическим преобразованием типов. Ну, чтобы можно было, например, проинициализировать массив струкур вот так:
struct A
{
public A(int value) { Value = value; }
public int Value;
}
...
A[] array = { 1, 2, 3 };
И вообще, вывод типов мощьнейшая вещь. Его нужно бы в язык интегрировать по полной.
AVK>2) Расширяющие методы (Extension methods). Хитрая штука. Позволяет объявлять статические методы с параметром this и привязывать их в качестве метода экземпляра к существующим классам.
Вау!!! Я даже не ожидал. Может они нашу философию читают? Хотя не конечно... скорее всего они читают языковую группу С++. Это же предлагалось в следующий стандарт плюсов. Почти уверен, что старперы из плюсового комитета ее заверну. А в шарпе будет. Уря!
Вот и ответ на все несоотвестия. Таки теперь мы будет иметь нормальный ОО-синтаксис вызова методов расширения. В общем, объект все что качается, если не качается, то раскачивается и признается объектом.
AVK>Сахар конечно, но забавно.
Э... Не скажи. Это очень правильное решение. Это устраняет одно из серьезных несоотвествий. Теперь никакой педант не скажет, что ToString() ошибка, так как нельзя сделать ToMyClass().
Единообразие много стоит.
AVK>Обсуждается необходимость расширяющих свойств, событий и операторов, но пока такое не поддержвается.
Логично было бы позволить добавлять любые типы членов кроме пожалуй перменных.
AVK>3) Лямбда-выражения. Выражения, служащие для написания программ в функциональном стиле. Вобщем то в 2.0 анонимные методы очень на это похожи, но в 3.0 сделана попытка преобразовать внешний вид к более функциональному стилю. Для этого введен новый токен — =>. AVK>Пример: AVK>
AVK>delegate R Func<A,R>(A arg);
AVK>...
AVK>Func<int,int> f1 = x => x + 1; // Ok
AVK>Func<int,double> f2 = x => x + 1; // Ok
AVK>Func<double,int> f3 = x => x + 1; // Error
AVK>
То есть это только сахар? Хотя конечно и это полезно. Уж больно много места занимает никчемное ключевое слово delegate и описание параметров анонимного метода.
Однако для полноценного применения функционального стиля нужно сделать еще два шага. Во первых ввести передачу лямд без делегатов, чтобы можно было делать лямбда-преоразования и соответсвенно строить методы из кусков, а во-вторых, компилятор должен научиться боросться с двойной рекурсией и вообще преобразовывать концевую рекусию в циклы, чтобы можно было полноценно использовать рекурсию вместо циклов.
AVK>Любители функционального стиля будут довольны.
Зависит от реализации.
AVK> Хотя возможность творить на этой базе извраты (особенно если совместно с дженериками) меня пугает.
Гы. Не боись. У функционального стиля большой потенциал. А ламерам останется Васик. Так что проблем нет.
AVK>4) Инициализаторы объектов и коллекций (Object and collection initializers). Позволяют в одном выражении вызвать конструктор и присвоить ряд значений. Сахарок для улучшения читаемости кода. AVK>Примеры: AVK>
AVK>var a = new Point { X = 0, Y = 1 };
AVK>// which has the same effect as
AVK>// var a = new Point();
AVK>// a.X = 0;
AVK>// a.Y = 1;
Ё! И об этом говорили большивеки в "Философии". Эх если бы они нас читали, то все это могло бы появиться еще в двушке. :(
AVK>Не уверен, но по идее должно работать и так:
AVK>[c#]
AVK>var dict = new Dictionary<string, int> {
AVK> new KeyValuePair<string, int>("one", 1),
AVK> new KeyValuePair<string, int>("two", 2),
AVK> new KeyValuePair<string, int>("three", 3)
AVK>}
AVK>
А что tuple-ы они не ввели? Если ввели (что логично учитывая акцент на функциональном стиле), то все эти извраты больше не нужны и код может выглядеть как-то так:
var dict = new Dictionary<string, int>
{
("one", 1), ("two", 2), ("three", 3)
};
Где груглые скобки означают создание кортежей (tuple-ов).
AVK>5. Анонимные типы. Проистекают из возможностей в п.1 и п.4. На основании объектного инициализатора выводится тип.
Гы. Это же они и есть — tuple-ы.
Так что предыдущий пример должен будет выглядеть так:
var dict = new Dictionary<string, int>
{
new { "one", 1 }, new { "two", 2 }, new { "three", 3 }
};
Хотя нафиг нужны эти "new" не ясно. Ну, да и так сойдет. Чай не Лисп.
AVK>
AVK>var p1 = new { Name = "Lawnmower", Price = 495.00 };
AVK>var p2 = new { Name = "Shovel", Price = 26.95 };
AVK>p1 = p2;
AVK>// Компилятор неявно создает следующий класс:
AVK>// class __Anonymous1
AVK>{
AVK> private string _name;
AVK> private double _price;
AVK> public string Name { get {return _name;} set {_name = value;}}
AVK> public double Price { get {return _price;} set {_price = value;}}
AVK>}
AVK>
А с чего он взял, что Name и Price — это свойства, а не поля?
AVK>Прикольно. К сожалению, если я правильно понял, использовать такие типы без рефлекшена или делегатов можно только внутри одного метода.
Не. Ты точно не правильно понял. Анонимные типы == кортежи. Кортежи сравниваются по значению и должны мочь использоваться везде где применимы длругие типы. Но должен быть синтаксис описания анонимных типов без декларации. Тогда их можно будет использовать как возвращаемые занчения функций и как параметры функций. Корче это неотемлемая часть функционального стиля!
AVK>6. Неявно типизированные массивы. Тоже сахарок, позволяющий не указыватьв new тип массива. AVK>
Ну, это продолжение идеи вывода типов. Ничем от неявных локальных переменных не отличается. В общем, верным путем идут товарищи.
AVK>7. Выражения запроса. (Query expressions). В новый язык добавлены декларативные конструкции, похожие на SQL. AVK>Можно писать так: AVK>
AVK>from c in customers
AVK>where c.City == "London"
AVK>from o in c.Orders
AVK>where o.OrderDate.Year == 2005
AVK>select new { c.Name, o.OrderID, o.Total }
AVK>
Нда, похоже на нечто новое. Хотя...
AVK>ИМХО изврат редкостный. Насколько это будет полезно я пока ответить затрудняюсь.
...хотя очень уж смахивает на list comprehension из таких языков как Питон, Хаскель и т.п. Вообще штука забавная, но уж больно диковинно реализованно. Хотя я могу ошибаться. Тут нужно попробовать на практике.
AVK>8. Дерево выражений. Лямбда-выражения преобразуются компилятором в анонимные методы. Однако есть возможность сохранять эти самые выражения ввиде структуры с данными, которые умеют потом, в рантайме, при помощи эмита генерить эти самые методы: AVK>
AVK>Func<int,int> f = x => x + 1; // Code
AVK>Expression<Func<int,int>> e = x => x + 1; // Data
AVK>
AVK>Зачем это нужно пока не сказано. Все что есть: AVK>
Expression trees are efficient in-memory data representations of lambda expressions and make the structure of the expression transparent and explicit.
AVK>Вот так — прозрачные и явные. Попой чую, что для каких то особо хитрых извратств в рантайме (скорее всего связанных с п.7), но чего то вечером пример придумать не могу. Ну разве что такую лямбду можно будет сериализовать (к примеру, чтобы сохранить в БД или передать по сети).
Гы. Темнота. Это такой изращенческий способ открыть дверь в мир лямбда-исчислений, а точнее лямбда-конверсий, т.е. в мир комбинаторной логики. Дело в том, что делегаты далеко не самый эффективный способ работы с функциями. Они приводят к динамическому полиморфизму, что как минимум медленее нежели статический. Теория лямбда-конверсий подразумевает, что над методами можно производить разные вычисления какбудто это объекты. Таким образом можно из одних методов создавать другие. Причем результат может быть очень и очень забавным.
Ты думашь от чего так фэны Лиспа прославляют его макросы? Если я правильно поня, то данная штука позволит если не заткнуть макросы Лиспа за пояс, то хотя бы дать такие же мощьные возможноти в наш арсенал. Если все как я понимаю, и если ребатам из МС удастся реализовать все как надо, то можно будет заниматься метапрограммирование не отходя от кассы... тфу ты прямо в C#.
Про операциями над этими выражениями ничего не сказано?
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали: VD>Вот и ответ на все несоотвестия. Таки теперь мы будет иметь нормальный ОО-синтаксис вызова методов расширения. В общем, объект все что качается, если не качается, то раскачивается и признается объектом.
VD>Единообразие много стоит.
Интересно, можно ли в качестве this аргумента использовать интерфейс? А также интересно, как там с конфликтами имен.
Просто может появиться великолепная возможность придавать интерфейсам дефолтные реализации и утилитные методы. Примерно так:
public static string Concat(this IEnumerable self, string separator)
{
StringBuilder sb = new StringBuilder();
foreach(object o in self)
{
sb.Append(o);
sb.Append(separator);
}
if (sb.Length > 0)
sb.Length -= separator.Length;
}
И это даст возможность писать .Concat(";") для любого IEnumerable. VD>Логично было бы позволить добавлять любые типы членов кроме пожалуй перменных.
Полностью согласен.
Для бизнес-объектов это великая штука. Вот были у нас объекты Customer. А теперь мы дописываем cборку Orders, и у Customer появляется коллекция .Orders.
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
AVK>2) Расширяющие методы (Extension methods). Хитрая штука. Позволяет объявлять статические методы с параметром this и привязывать их в качестве метода экземпляра к существующим классам.
О! Это здорово! Это то, что в Delphi последней назвается helper-классом.
AVK>Любители функционального стиля будут довольны. Хотя возможность творить на этой базе извраты (особенно если совместно с дженериками) меня пугает.
Мда, извраты с печальными результатами (что без поллитры не разберешься) мы уже видели для C# 2.0.
AVK>5. Анонимные типы. Проистекают из возможностей в п.1 и п.4. На основании объектного инициализатора выводится тип.
Что-то вроде tuples.
AVK>7. Выражения запроса. (Query expressions). В новый язык добавлены декларативные конструкции, похожие на SQL.
Здравствуйте, Igor Trofimov, Вы писали:
iT>Мда, извраты с печальными результатами (что без поллитры не разберешься) мы уже видели для C# 2.0.
Блин, Дельфи и Васики живы и ждут всех кто не привык напрягать извилины.
AVK>>5. Анонимные типы. Проистекают из возможностей в п.1 и п.4. На основании объектного инициализатора выводится тип.
iT>Что-то вроде tuples.
Они и есть. У МС духу не хватает назвать скомунизженные парадигмы своими именами. Удивительно как они лямбду лямбдой назвали.
AVK>>7. Выражения запроса. (Query expressions). В новый язык добавлены декларативные конструкции, похожие на SQL.
iT>Imho, полный изврат.
Может дял начала разобраться и попробовать?
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, iZEN, Вы писали:
ZEN>Язык программирования явно тяготеет к разговорному английскому. А оно надо?
Язык слава богу впитывает самые вреные и правильные концпции разработанные учеными в последние 30 лет. Для всех кто не способен понять или принять это есть другие языки.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
iT>>Мда, извраты с печальными результатами (что без поллитры не разберешься) мы уже видели для C# 2.0.
VD>Блин, Дельфи и Васики живы и ждут всех кто не привык напрягать извилины.
А для Васика тоже новую версию выложили с похожими изменениями. Я, правда, не смотрел.
VD>Они и есть. У МС духу не хватает назвать скомунизженные парадигмы своими именами.
Хватило. В какой то из док это слово даже проскакивало.
iT>>Imho, полный изврат.
VD>Может дял начала разобраться и попробовать?
С утречка думал — все таки слишком узкоспециализированная штука. ИМХО лучше бы они ввели возможность прикладному программисту создавать что то подобное на основе базовой механики. Чтобы можно было делать не только sql-like, но и, к примеру, xpath-like код.
Здравствуйте, iZEN, Вы писали:
AVK>>В качестве основной цели задекларированна поддержка функционального стиля. ZEN>Резюме. ZEN>Язык программирования явно тяготеет к разговорному английскому.
Неа. Функциональный стиль это скорее математика и лямбда-исчисление.
ZEN> А оно надо?
Здравствуйте, VladD2, Вы писали:
AVK>>1) Неявно типизированные локальные переменные (implicitly typed local variable). То о чем долго говорили большевики в форуме философия. Даже ключевое слово народ там угадал.
VD>Ха! Большивики еще говорили о том, что разумно было бы ввести неизменяемые локальные переменне.
Это из другой оперы. Большевики еще, к примеру, очень долго говорили, что одним из самых больших недостатков императивных возможностей шарпа является отсутствие возможности подключения реализаций. Тем не менее воз и ныне там.
VD>А вообще, МС как всегда реализует чужие идеи называя их своими инменами. Это дело в исходном виде называлось "вывод типов" (type inference).
Вот бы еще они mixins скоммунизьмили.
VD>Вот и ответ на все несоотвестия. Таки теперь мы будет иметь нормальный ОО-синтаксис вызова методов расширения. В общем, объект все что качается, если не качается, то раскачивается и признается объектом.
Ну, надо признать, что в Delphi.NET похожее уже есть.
AVK>>Сахар конечно, но забавно.
VD>Э... Не скажи. Это очень правильное решение. Это устраняет одно из серьезных несоотвествий. Теперь никакой педант не скажет, что ToString() ошибка, так как нельзя сделать ToMyClass().
VD>Единообразие много стоит.
ХЗ. ИМХО вопрос культуры программирования. С точки зрения архитектурных проблем это ничего не дает. А меня это волнует в первую очередь.
AVK>>Обсуждается необходимость расширяющих свойств, событий и операторов, но пока такое не поддержвается.
VD>Логично было бы позволить добавлять любые типы членов кроме пожалуй перменных.
Возможно, как с дженерик-свойствами, есть какие то синтаксические проблемы. Т.е. для методов добавление модификатора к параметру естественно, а вот со свойствами и событиями уже не так очевидно и требует сурового перетряхания грамматики. А вот почему операторы не добавили — ХЗ.
AVK>>3) Лямбда-выражения. Выражения, служащие для написания программ в функциональном стиле. Вобщем то в 2.0 анонимные методы очень на это похожи, но в 3.0 сделана попытка преобразовать внешний вид к более функциональному стилю. Для этого введен новый токен — =>. AVK>>Пример: AVK>>
AVK>>delegate R Func<A,R>(A arg);
AVK>>...
AVK>>Func<int,int> f1 = x => x + 1; // Ok
AVK>>Func<int,double> f2 = x => x + 1; // Ok
AVK>>Func<double,int> f3 = x => x + 1; // Error
AVK>>
VD>То есть это только сахар?
Все, что сейчас описано это сахар, потому что существующая реализация работает на 2 фреймворке.
VD> Хотя конечно и это полезно. Уж больно много места занимает никчемное ключевое слово delegate и описание параметров анонимного метода.
+1
VD>Однако для полноценного применения функционального стиля нужно сделать еще два шага. Во первых ввести передачу лямд без делегатов, чтобы можно было делать лямбда-преоразования и соответсвенно строить методы из кусков,
Возможно можно будет что то соорудить на базе expression tree.
AVK>> Хотя возможность творить на этой базе извраты (особенно если совместно с дженериками) меня пугает.
VD>Гы. Не боись. У функционального стиля большой потенциал. А ламерам останется Васик.
Не факт . В нем тоже может многое из этого появится. Надо глядеть. Да и потом — для любителей извратов есть С++/CLI
VD>Ё! И об этом говорили большивеки в "Философии".
Как то прошло мимо моего глаза.
VD>Гы. Это же они и есть — tuple-ы.
VD>Так что предыдущий пример должен будет выглядеть так: VD>
VD>var dict = new Dictionary<string, int>
VD>{
VD> new { "one", 1 }, new { "two", 2 }, new { "three", 3 }
VD>};
VD>
Не, это работать не будет. Во-первых это просто неверный синтаксис, правильно так:
var dict2 = new Dictionary<string, int>
{
new { Key = "one", Value = 1 },
new { Key = "two", Value = 2 },
new { Key = "three", Value = 3 }
};
Потом, компилятор создаст свой класс, а в collection initializer нужно тот тип, который T в реализованном ICollection<T>. Т.е., в случае Dictionary это KeyValuePair. Текущий компилятор на такой код говорит следующее:
TupleDic.cs(15,9): error CS0029: Cannot implicitly convert type 'Test.<Projection>f__0' to 'System.Collections.Generic.KeyValuePair<string,int>'
Да, еще компилятор не понимает явную реализацию интерфейсов, так что даже мой вариант не компилируется, говорит что:
TupleDic.cs(7,42): error CS1501: No overload for method 'Add' takes '1' arguments
Хотя в спецификации написано, то он будет искать Add именно у ICollection<T> (и иногда так и делает, судя по предыдущей ошибке). ИМХО просто баг.
VD>А с чего он взял, что Name и Price — это свойства, а не поля?
С того, что так написано в спецификации.
VD>Не. Ты точно не правильно понял. Анонимные типы == кортежи. Кортежи сравниваются по значению и должны мочь использоваться везде где применимы длругие типы. Но должен быть синтаксис описания анонимных типов без декларации. Тогда их можно будет использовать как возвращаемые занчения функций и как параметры функций. Корче это неотемлемая часть функционального стиля!
Может быть. Но если ты приведешь компилируемый пример, тогда я поверю. Пока же, по текущей спецификации, это не работает. Единственное — компилятор на одинаковые объявления генерирует один и тот же класс. Это видно в самой последней строчке примера.
AVK>>ИМХО изврат редкостный. Насколько это будет полезно я пока ответить затрудняюсь.
VD>...хотя очень уж смахивает на list comprehension из таких языков как Питон, Хаскель и т.п. Вообще штука забавная, но уж больно диковинно реализованно. Хотя я могу ошибаться. Тут нужно попробовать на практике.
ИМХО слишком узкоспециализированно.
VD>Гы. Темнота. Это такой изращенческий способ открыть дверь в мир лямбда-исчислений, а точнее лямбда-конверсий, т.е. в мир комбинаторной логики. Дело в том, что делегаты далеко не самый эффективный способ работы с функциями. Они приводят к динамическому полиморфизму, что как минимум медленее нежели статический. Теория лямбда-конверсий подразумевает, что над методами можно производить разные вычисления какбудто это объекты. Таким образом можно из одних методов создавать другие. Причем результат может быть очень и очень забавным.
Но из текущей спецификации ничего такого не видно.
VD>Про операциями над этими выражениями ничего не сказано?
Нет. Там почти ничего не рассказано про эту фишку.
Здравствуйте, GlebZ, Вы писали:
AVK>>Нет тут никакой дыры. Не забывай, что это синтаксический сахар. GZ>Эдак весь C# можно считать синтаксическим сахаром для CLI.
Можно. Никакие проблемы в компиляторе не должны приводить к нарушению безопасности, потому что она работает на уровне рантайма.
Здравствуйте, TK, Вы писали:
VD>>Ну, нельзя делегат в дерево превратить. Дерево нужно иметь зараниее. Так что как я понимаю, это все только дополнительные возможности.
TK>Что-то ты не правильно понимаешь...
... или ты.
TK>>>Именно по этому AST и генерируются SQL запросы VD>>Ну, так его принимают только отдельные функции. А разные Where и.п. принимают на вход делегаты.
TK>Кто тебе такое сказал?
Декомпиляторы и описание стандарта:
26.7.2 The query expression pattern
The Query Expression Pattern establishes a pattern of methods that types can implement to support query expressions. Because query expressions are translated to method invocations by means of a syntactic mapping, types have considerable flexibility in how they implement the query expression pattern. For example, the methods of the pattern can be implemented as instance methods or as extension methods because the two have the same invocation syntax, and the methods can request delegates or expression trees because lambda expressions are convertible to both.
The recommended shape of a generic type C<T> that supports the query expression pattern is shown below. A generic type is used in order to illustrate the proper relationships between parameter and result types, but it is possible to implement the pattern for non-generic types as well.
delegate R Func<A,R>(A arg);
class C<T>
{
public C<T> Where(Func<T,bool> predicate);
public C<S> Select<S>(Func<T,S> selector);
public C<S> SelectMany<S>(Func<T,C<S>> selector);
public O<T> OrderBy<K>(Func<T,K> keyExpr);
public O<T> OrderByDescending<K>(Func<T,K> keyExpr);
public C<G<K,T>> GroupBy<K>(Func<T,K> keyExpr);
public C<G<K,E>> GroupBy<K,E>(Func<T,K> keyExpr, Func<T,E> elemExpr);
}
class O<T> : C<T>
{
public O<T> ThenBy<K>(Func<T,K> keySelector);
public O<T> ThenByDescending<K>(Func<T,K> keySelector);
}
class G<K,T>
{
public K Key { get; }
public C<T> Group { get; }
}
TK> Есть разные реализации. Одни принимают на вход делегаты а другие Expressions. Те которые принимают Expressions умеют по ним генерировать нормальный SQL
В том, то и дело, что умеют принимать этот самый Expression очень не многие методы.
Ладно. Тут нужно копать глубже.
ЗЫ
Ты кстит, не понял как превратить это АСТ в МСИЛ? Что-то я никак не въеду.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
26.7.2 The query expression pattern
The Query Expression Pattern establishes a pattern of methods that types can implement to support query expressions. Because query expressions are translated to method invocations by means of a syntactic mapping, types have considerable flexibility in how they implement the query expression pattern. For example, the methods of the pattern can be implemented as instance methods or as extension methods because the two have the same invocation syntax, and the methods can request delegates or expression trees because lambda expressions are convertible to both.
The recommended shape of a generic type C<T> that supports the query expression pattern is shown below. A generic type is used in order to illustrate the proper relationships between parameter and result types, but it is possible to implement the pattern for non-generic types as well.
То есть по идее таки можно запомнить несколько where в ExpressionTree, а потом при попытке проитерироваться по результату выполнить SQL запрос сконструированный из них.
Здравствуйте, VladD2, Вы писали:
_FR>>А зачем они делегат Func (из System.Query) назвали сокращённо? Есть же прекрасное слово Function _FR>>Надеюсь, поправят
VD>Это еще что. А вон зачем было запихивать делегаты общего назначения в пространство имен System.Query?
Я даже сперва подумал, что лямбды ни во что, кроме Func<x, ...> преобразовываться не умеют
Да и давно уже пора пользоваться CommonGenericsLibrary
Здравствуйте, Dr.Gigabit, Вы писали:
_FR>>На PDC 2005 _FR>>Вот, блин, дают Кто-нибудь бывает на таких мероприятиях?
DG>Теоретически, сейчас такая возможность есть у любого. здесь DG>Стоит только захотеть
Не... Не люблю тусовки, хотя по слухам к ним и в джинсах можно.. но за инфу всё равно спасибо, мне казалось, что появиться на такой тусовке не просто.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Dkm_S, Вы писали:
D_S>Пока второго никак не дождёмся — а уж третьего чего бояться-то? D_S>Много чего перемениться может...
Рискну предположить, что и должно Но пока никаких документов, окромя намёков на СиОмегу не встречал Но не о предположениях же они собираются докладывать, но о выбранной стратегии, я надеюсь.
<< RSDN@Home 1.1.4 beta 7 rev. 474 >> [Windows XP — 5.1.2600.0]
under «*none*»
Help will always be given at Hogwarts to those who ask for it.
>Вот, блин, дают Кто-нибудь бывает на таких мероприятиях?
Конечно, бывают. Часть по приглашению Microsoft, а часть за свои денежки или за денежки компании.
Здравствуйте, Torero, Вы писали:
T>>Вот, блин, дают Кто-нибудь бывает на таких мероприятиях? T>Конечно, бывают. Часть по приглашению Microsoft, а часть за свои денежки или за денежки компании.
А общее кол-во тусовщиков — несколько сотен или тыщ?
<< RSDN@Home 1.1.4 beta 7 rev. 474 >> =07:00= [Windows XP — 5.1.2600.0]
under «*none*»
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, fuurin, Вы писали:
_FR>>На PDC 2005 _FR>>Вот, блин, дают Кто-нибудь бывает на таких мероприятиях?
F>Здесь страничка появилась "Visual C# Home > Future Versions". Среди прочего там лежит "csharp 3.0 specification.doc" — набросок новых фич в третьей версии.
Здравствуйте, _FRED_, Вы писали:
_FR>Рискну предположить, что и должно Но пока никаких документов, окромя намёков на СиОмегу не встречал Но не о предположениях же они собираются докладывать, но о выбранной стратегии, я надеюсь.
Здравствуйте, AndrewVK, Вы писали:
AVK>2) Расширяющие методы (Extension methods). Хитрая штука. Это получается так:
//я написалpublic MyCryptoClass
{
public Crypt(){CryptForSecure();};
}
//доброжелатель ответилpublic static class Extensions
{
public static Crypt(this MyCryptoClass class){SaveForUnsecure();};
}
Занятненько.
AVK>Класс, для которого разрешены такие фокусы, должен выглядеть примерно так:
... AVK>ИМХО изврат редкостный. Насколько это будет полезно я пока ответить затрудняюсь.
Это для стандартных generic коллекций заготовлено. Очевидно будут и шаблоны для custom коллекций.
The Standard Query Operators (described in a separate specification) provide an implementation of the query operator pattern for any type that implements the System.Collections.Generic.IEnumerable<T> interface.
AVK>8. Дерево выражений. Лямбда-выражения преобразуются компилятором в анонимные методы. AVK>Вот так — прозрачные и явные. Попой чую, что для каких то особо хитрых извратств в рантайме (скорее всего связанных с п.7), но чего то вечером пример придумать не могу. Ну разве что такую лямбду можно будет сериализовать (к примеру, чтобы сохранить в БД или передать по сети).
[imho]Возможно даже не для сериализации, а для ленивых вычислений. Особенно для Query это очень уместно. К тому-же обычно такие запросы можно оптимизировать. Возможно это будет редактируемый план выполнения.
Здравствуйте, AndrewVK, Вы писали:
AVK>В качестве основной цели задекларированна поддержка функционального стиля.
Резюме.
Язык программирования явно тяготеет к разговорному английскому. А оно надо?
Re: Краткий пересказ
От:
Аноним
Дата:
14.09.05 20:07
Оценка:
V etom godu bolee 10000 uchastnikov.
Segodnja budu na dvuh dokladah po C# v.3 i LINQ projects.
Prichem eto ne tolko spec, no i uje rabotaet.
Office 12 anonsirovali. Jalko chto ne dali disk s nim.
_FR>>На PDC 2005 _FR>>Вот, блин, дают Кто-нибудь бывает на таких мероприятиях?
F>Здесь страничка появилась "Visual C# Home > Future Versions". Среди прочего там лежит "csharp 3.0 specification.doc" — набросок новых фич в третьей версии. F>А 22-го сентября будет чат с обсуждением C# 3.0 Language Enhancements, 1:00 — 2:00 P.M. Pacific time.
Если так дело пойдет и дальше, то скора появится спецификация для 10-ой версии языка.
Ведь ахринеть ведь можно. 2-я версия еще не зарелизена, а на сайте уже доступны спецификации 3-ей.
То ли дело плюсовый комитет. По 11+ лет между стандартами. К половину сроку треть компиляторов осваивают 90% фич стандарта... В общем, прогесс в замедленном повторе.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, _FRED_, Вы писали:
F>>Здесь страничка появилась "Visual C# Home > Future Versions". Среди прочего там лежит "csharp 3.0 specification.doc" — набросок новых фич в третьей версии.
_FR>Вы только оглавление посмотрите:
Хачу, хачу, хачу... (с) девочка у зациклившегося проирывателя произносящего фразу "хочешь я расскажу тебе сказку".
В общем, дайте телефон Хегельберага пойду его трясти чтобы альфу дал.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, ceo, Вы писали:
ceo>I can only show you the door.
А я могу показать куда зайти, чтобы не транслитить на весь интернет.
Вот http://www.translit.ru/ замечательный сайтик. Избавляет от проблем транслита на раз.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Краткий пересказ
От:
Аноним
Дата:
14.09.05 23:26
Оценка:
Спасибо за ссылку.
Давайте определимся. Версия языка и платформи — это разние вещи. Просто так совпало что вторая версия C# и .Net виходят одновременно. Сейчс идет речь о версии языка. Т.е. выпустят раширение для компилятора и студии.
Здравствуйте, Аноним, Вы писали:
А>Флеш-моб может устроить ? Всем россиянам, кто будет принимать участие — явиться в шапках-ушанках с бутылкой водки в кармане и с карманным медведем на поводке
Что-то я вас в упор не вижу
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, VladD2, Вы писали:
VD>Не. Ты точно не правильно понял. Анонимные типы == кортежи. Кортежи сравниваются по значению и должны мочь использоваться везде где применимы длругие типы. Но должен быть синтаксис описания анонимных типов без декларации. Тогда их можно будет использовать как возвращаемые занчения функций и как параметры функций. Корче это неотемлемая часть функционального стиля!
По крайней мере в сиомеге обсуждалось именно это. Там анонимный тип полностью определяется типами своих компонентов. При этом имена аргументов в расчет не принимаются — они всего лишь позволяют обращаться напрямую к компонентам, используя привычную точку. Была вроде также ограниченная совместимость этих типов, похожая на совместимость массивов. Ну, типа { string, string} можно привести к { object, object }.
При этом также, как для дженериков, независимые одинаковые спецификации порождают один и тот же тип. Т.е. если у тебя в одном месте порождается {string, string} и кастится к object перед отдачей, то в другом месте ты сможешь снова откастить это к {string, string}.
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
AVK>2) Расширяющие методы (Extension methods). Хитрая штука. Позволяет объявлять статические методы с параметром this и привязывать их в качестве метода экземпляра к существующим классам. AVK>Объявляются такие методы как обычные, но перед первым параметром добавляется модификатор this. AVK>
AVK>namespace Acme.Utilities
AVK>{
AVK> public static class Extensions
AVK> {
AVK> public static int ToInt32(this string s) {
AVK> return Int32.Parse(s);
AVK> }
AVK> public static T[] Slice<T>(this T[] source, int index, int count) {
AVK> if (index < 0 || count < 0 || source.Length – index < count)
AVK> throw new ArgumentException();
AVK> T[] result = new T[count];
AVK> Array.Copy(source, index, result, 0, count);
AVK> return result;
AVK> }
AVK> }
AVK>}
AVK>
Забавно, как в Ruby прямо ( тока там синтаксис еще проще )
VD>А что tuple-ы они не ввели? Если ввели (что логично учитывая акцент на функциональном стиле), то все эти извраты больше не нужны и код может выглядеть как-то так: VD>
Что ты этим кодом хотел сказать?
GZ>[imho]Возможно даже не для сериализации, а для ленивых вычислений.
С этим и обычные лямбда-функции справяться, никакой необходимости в этом случае в кодогенерации нет. Я тут покумекал и кажется понял зачем они эту штуку ввели. Это нужно чтобы эффективно реализовывать на базе Query Expressions трехзвенные решения. На клиенте просто укатываем запрос в такой expression tree, а на сервере получаем готовый код, который не надо интерпретировать.
GZ> Особенно для Query это очень уместно. К тому-же обычно такие запросы можно оптимизировать. Возможно это будет редактируемый план выполнения.
Нет, этого не будет. Ты наверное неверно понял что это за штука. Никаких планов там нет, это просто описатель, по которому стандартная библиотека умеет емитом генерить код метода. Логика там примитивнейшая (скорее всего просто в ресурсах компилятор сохраняет скомпилированный IL-код). Очень вряд ли прикладной программист сможет вмешаться в процесс генерации этого кода. По крайней мере в текущей реализации этого точно нет.
Здравствуйте, Igor Trofimov, Вы писали:
AVK>>2) Расширяющие методы (Extension methods). Хитрая штука. Позволяет объявлять статические методы с параметром this и привязывать их в качестве метода экземпляра к существующим классам.
iT>О! Это здорово! Это то, что в Delphi последней назвается helper-классом.
Да, похоже. Хотя шарповский вариант более lightweight что ли.
AVK>>Любители функционального стиля будут довольны. Хотя возможность творить на этой базе извраты (особенно если совместно с дженериками) меня пугает.
iT>Мда, извраты с печальными результатами (что без поллитры не разберешься) мы уже видели для C# 2.0.
Ну пока это именно извратства, а не попытка сделать что то непредусмотренное.
AVK>>5. Анонимные типы. Проистекают из возможностей в п.1 и п.4. На основании объектного инициализатора выводится тип.
iT>Что-то вроде tuples.
Здравствуйте, VladD2, Вы писали:
F>>>Здесь страничка появилась "Visual C# Home > Future Versions". Среди прочего там лежит "csharp 3.0 specification.doc" — набросок новых фич в третьей версии.
_FR>>Вы только оглавление посмотрите:
VD>Хачу, хачу, хачу... (с) девочка у зациклившегося проирывателя произносящего фразу "хочешь я расскажу тебе сказку".
VD>В общем, дайте телефон Хегельберага пойду его трясти чтобы альфу дал.
Здравствуйте, mogadanez, Вы писали:
M>это не все что может tuple M>тогда при таком синтаксисе логично было бы уметь ее возвращать из функций, и присваивать списку переменных. M>примерно так:
Тогда скорее так
string a;
int b;
(a, b) = ("one", 1 );
или так
(string a; int b) = ("one", 1 );
или еще лучше так
(var a; var b) = ("one", 1 );
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Sinclair, Вы писали:
VD>>Единообразие много стоит. S>Интересно, можно ли в качестве this аргумента использовать интерфейс? А также интересно, как там с конфликтами имен.
V>А Extensions::Crypt разве перекрывает MyCryptoClass::Crypt? Если да — от это дыра
Нет тут никакой дыры. Не забывай, что это синтаксический сахар.
Таже вроде бы написано:
26.2.3 Extension method invocations
...
if the normal processing of the invocation finds no applicable instance methods (specifically, if the set of candidate methods for the invocation is empty), an attempt is made to process the construct as an extension method invocation.
Здравствуйте, AndrewVK, Вы писали:
AVK>Нет тут никакой дыры. Не забывай, что это синтаксический сахар.
Эдак весь C# можно считать синтаксическим сахаром для CLI.
Здравствуйте, AndrewVK, Вы писали:
AVK>Нет, этого не будет. Ты наверное неверно понял что это за штука. Никаких планов там нет, это просто описатель, по которому стандартная библиотека умеет емитом генерить код метода. Логика там примитивнейшая (скорее всего просто в ресурсах компилятор сохраняет скомпилированный IL-код). Очень вряд ли прикладной программист сможет вмешаться в процесс генерации этого кода. По крайней мере в текущей реализации этого точно нет.
Exercise 4 – Using Lambda Expressions to Create Expression Trees
In addition to treating data as objects, LINQ provides the ability to treat expressions as data at runtime. LINQ defines a new type, Expression<T>, that represents an expression tree, an in-memory representation of a lambda expression. Expression trees allow developers to treat lambda expressions as data, allowing for inspection and modification of lambda expressions in code. This feature will be used to enable an ecosystem of third-party libraries that leverage the base query abstractions that are part of LINQ. For example, a database access implementation might leverage this facility to translate expression trees into suitable query statements for a particular kind of database.
Здравствуйте, AndrewVK, Вы писали:
AVK>А для Васика тоже новую версию выложили с похожими изменениями. Я, правда, не смотрел.
Как мне жалко васиковцев . Ну, да мноие из них с VB 6.0 не слезли. Теперь похоже и не слезут.
VD>>Они и есть. У МС духу не хватает назвать скомунизженные парадигмы своими именами.
AVK>Хватило. В какой то из док это слово даже проскакивало.
Это видимо ошибка. Устранят к релизу.
AVK>С утречка думал — все таки слишком узкоспециализированная штука.
Я тоже глянул. Не очень то специализированное. Обработка списков одна из самых часто встречающихся задач. К тому же это только сахар. Все переписывается в функциональный силь. Так что это встроенный DSL.
AVK> ИМХО лучше бы они ввели возможность прикладному программисту создавать что то подобное на основе базовой механики. Чтобы можно было делать не только sql-like, но и, к примеру, xpath-like код.
Полностью согласен. Хорошим решением было бы введение макросов в стиле Лиспа или как предложил uw в стиле Nemerle.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
iT>>Что-то вроде tuples.
AVK>Они и есть.
Похоже что не совсем. В классических ФЯ tuples можно использовать для описания типов возвращаемых значений функций. А как это сделать в шарпе? Получается, что их можно использовать тлько в лямбдах и при описании вложенных структур (в списках и т.п.). Что не есть гуд.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, ceo, Вы писали:
ceo>Давайте определимся. Версия языка и платформи — это разние вещи. Просто так совпало что вторая версия C# и .Net виходят одновременно. Сейчс идет речь о версии языка. Т.е. выпустят раширение для компилятора и студии.
Несомненно разные. Но ведь еще не выпущен C# 2.0!
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
AVK>> ИМХО лучше бы они ввели возможность прикладному программисту создавать что то подобное на основе базовой механики. Чтобы можно было делать не только sql-like, но и, к примеру, xpath-like код.
Это средство трансформации. xpath — тут не катит(очевидно комега это хорошо показала). XQuery слишком завязан на xml. Здесь же практически чистый ассоциативный oql.
Вобщем, реляционный view который почему-то, кому-то, и зачем-то не хватало в ООП.
VD>Полностью согласен. Хорошим решением было бы введение макросов в стиле Лиспа или как предложил uw в стиле Nemerle.
Так что там предложил? (Ссылку исправь, пожалуйста).
Здравствуйте, Sinclair, Вы писали:
S>По крайней мере в сиомеге обсуждалось именно это. Там анонимный тип полностью определяется типами своих компонентов. При этом имена аргументов в расчет не принимаются — они всего лишь позволяют обращаться напрямую к компонентам, используя привычную точку. Была вроде также ограниченная совместимость этих типов, похожая на совместимость массивов. Ну, типа { string, string} можно привести к { object, object }.
В иеющемся компиляторе и спецификации это не так.
var x = new { X = 0, yield = 1 };
var y = new { Z = 0, yield = 1 };
Console.WriteLine(x == y);
Последняя строка выдает ошибку:
error CS0019: Operator '==' cannot be applied to operands of type 'LINQConsoleApplication1.Program.<Projection>f__0' and 'LINQConsoleApplication1.Program.<Projection>f__1'
А вот так:
var x = new { X = 0, yield = 1 };
var y = new { X = 0, yield = 1 };
Console.WriteLine(x == y);
прокатывает, но результат плачевный — False.
S>При этом также, как для дженериков, независимые одинаковые спецификации порождают один и тот же тип. Т.е. если у тебя в одном месте порождается {string, string} и кастится к object перед отдачей, то в другом месте ты сможешь снова откастить это к {string, string}.
В имеющемся компиляторе это невозможно. По спецификации тоже пишут, что безымянный тип недоступен.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, mogadanez, Вы писали:
M>это не все что может tuple M>тогда при таком синтаксисе логично было бы уметь ее возвращать из функций, и присваивать списку переменных.
M>примерно так:
M>
M>string a;
M>int b;
M>a,b = ("one, 1 );
M>
Возвращать из лямбд можно. Инициализировать ими списки тоже. Но вот описать тип функции ими не удастся.
Твой примет тоже не прокатывает. Но у полей есть имена, так что можно писать так:
var x = new { A = "one", B = 1 };
string a = x.A;
int b = x.B;
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
AVK>Это из другой оперы.
Как сказать.
AVK> Большевики еще, к примеру, очень долго говорили, что одним из самых больших недостатков императивных возможностей шарпа является отсутствие возможности подключения реализаций. Тем не менее воз и ныне там.
Это да.
AVK>Вот бы еще они mixins скоммунизьмили.
Опять таки смотря как это будет реализовано. А вот что они сделали с кортежами мне очень не нарвится. Решение убогое и половинчатое.
VD>>Вот и ответ на все несоотвестия. Таки теперь мы будет иметь нормальный ОО-синтаксис вызова методов расширения. В общем, объект все что качается, если не качается, то раскачивается и признается объектом.
AVK>Ну, надо признать, что в Delphi.NET похожее уже есть.
Думашь, только в МС читают форумы посвященные стандартизации С++? К тому же уверен, что фишка уже реализована в других языках за долго до того как она попала в Дельфи.
AVK>ХЗ. ИМХО вопрос культуры программирования. С точки зрения архитектурных проблем это ничего не дает. А меня это волнует в первую очередь.
Это дает логичный и более краткий код. Мелочь казалось бы, но если вспомнить чем отличается ассемблер от языков высокого уровня...
AVK>Возможно, как с дженерик-свойствами, есть какие то синтаксические проблемы. Т.е. для методов добавление модификатора к параметру естественно, а вот со свойствами и событиями уже не так очевидно и требует сурового перетряхания грамматики. А вот почему операторы не добавили — ХЗ.
Возможно.
VD>>То есть это только сахар?
AVK>Все, что сейчас описано это сахар, потому что существующая реализация работает на 2 фреймворке.
У тебя странное понятие сахара. Итераторы по-твоему тоже сахар?
VD>>Однако для полноценного применения функционального стиля нужно сделать еще два шага. Во первых ввести передачу лямд без делегатов, чтобы можно было делать лямбда-преоразования и соответсвенно строить методы из кусков,
AVK>Возможно можно будет что то соорудить на базе expression tree.
Пока что я не понял как из них получить скомпилированный код.
AVK>Не факт . В нем тоже может многое из этого появится. Надо глядеть. Да и потом — для любителей извратов есть С++/CLI
Тут уже любители С++ смогут на поном основании говорить о том к кого какие картиночки.
AVK>Не, это работать не будет. Во-первых это просто неверный синтаксис, правильно так: AVK>
AVK>var dict2 = new Dictionary<string, int>
AVK>{
AVK> new { Key = "one", Value = 1 },
AVK> new { Key = "two", Value = 2 },
AVK> new { Key = "three", Value = 3 }
AVK>};
AVK>
Ну, да... им нужны имена. Уроды, былин.
AVK>Потом, компилятор создаст свой класс, а в collection initializer нужно тот тип, который T в реализованном ICollection<T>. Т.е., в случае Dictionary это KeyValuePair. Текущий компилятор на такой код говорит следующее:
С какого интересно перепуга нельзя добавить в Dictionary конструктор принимающий new { Key = "...", Value = ... }? AVK>
AVK>TupleDic.cs(15,9): error CS0029: Cannot implicitly convert type 'Test.<Projection>f__0' to 'System.Collections.Generic.KeyValuePair<string,int>'
AVK>
Дык коллекции то старые. Параметра нет. Вот и все.
VD>>А с чего он взял, что Name и Price — это свойства, а не поля?
AVK>С того, что так написано в спецификации.
Нда, дурь. Что-то они с этими анонимными типами намудрили. Видимо будет такой же критинизм как с анонимными методами, когда сначало выйдет дебильная версия, а потом они почешут репу и скажут — надо бы поправить.
VD>>Не. Ты точно не правильно понял. Анонимные типы == кортежи. Кортежи сравниваются по значению и должны мочь использоваться везде где применимы длругие типы. Но должен быть синтаксис описания анонимных типов без декларации. Тогда их можно будет использовать как возвращаемые занчения функций и как параметры функций. Корче это неотемлемая часть функционального стиля!
AVK>Может быть. Но если ты приведешь компилируемый пример, тогда я поверю.
Я уже проверил. Уроды они. Анонимные типы пока что < кортежи.
AVK> Пока же, по текущей спецификации, это не работает. Единственное — компилятор на одинаковые объявления генерирует один и тот же класс. Это видно в самой последней строчке примера.
Ага, вот только экземляры даже одинаковые сравниваются по адерсам и:
var x = new { X = 0, yield = 1 };
var y = new { X = 0, yield = 1 };
Console.WriteLine(x == y);
возвращает False.
Ну, что за дебилы это разрабатывали? Ну, неужели нельзя было просто скомуниздить идею кортежей 1 в 1? И ведь в роде в это СиОмеге все грамотно было сделано! Может они просто недоделали?
VD>>...хотя очень уж смахивает на list comprehension из таких языков как Питон, Хаскель и т.п. Вообще штука забавная, но уж больно диковинно реализованно. Хотя я могу ошибаться. Тут нужно попробовать на практике.
AVK>ИМХО слишком узкоспециализированно.
Наоборот. list comprehension намного более узкое решение. Это как гигантский foreach. Синтаксический сахар над паттерном проектирования.
Это решение уж точно не уже foreach-а. Другое дело, что конечно такие вещи нужно не в язык встраивать, а делать средства расширения языка чтобы их можно было делать оп своему разумению.
VD>>Гы. Темнота. Это такой изращенческий способ открыть дверь в мир лямбда-исчислений, а точнее лямбда-конверсий, т.е. в мир комбинаторной логики. Дело в том, что делегаты далеко не самый эффективный способ работы с функциями. Они приводят к динамическому полиморфизму, что как минимум медленее нежели статический. Теория лямбда-конверсий подразумевает, что над методами можно производить разные вычисления какбудто это объекты. Таким образом можно из одних методов создавать другие. Причем результат может быть очень и очень забавным.
AVK>Но из текущей спецификации ничего такого не видно.
Видно. Просто в спецификации пара слов всего. А вот в компиляторе уже по более. Плюс два примера есть. Жаль что они слишком огромные. Но похоже это именно возможность заставить преобразовать код в АСТ и обратно. Какого хрена не сделать это для любой конструкции и не позволить делать преобразования во время компиляции я не знаю. А было бы удобно. Ну, да возможно и без того будет круто.
VD>>Про операциями над этими выражениями ничего не сказано?
AVK>Нет. Там почти ничего не рассказано про эту фишку.
Ну, на операции я уже посморел. Чистое АСТ которое можно менять как хочешь. Только не понял как из него получить скомпилированный код.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
То ест предоставляют возможность создать динамический запрос.
Но сам DLinq — это синтаксический сахар который преобразует SQL-подобные выражения в банальный код в функциональном стиле. Вот пример из описания DLinq-я:
from c in customers, o in c.Orders
where o.OrderDate.Year == 2005
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total }
Expression trees же позволяют построить АСТ кода. Упомянутое же АВК объявление — это возможность заставить компилятор вместо МСИЛ-а породить АСТ указанного лямбды. Например:
using System;
using System.Expressions;
using System.Query;
class Program
{
static void Main()
{
// просто лямбда
Func<int, int> lambda = x => x * x;
Console.WriteLine(lambda); // выводит System.Query.Func`2[System.Int32,System.Int32]
Console.WriteLine(lambda(2)); // выводит 4
// лямбда преобразуемая в дерево выражений.
Expression<Func<int, int>> lambdaExpression = x => x * x;
Console.WriteLine(lambdaExpression); // выводит |x| Multiply(x, x)
}
}
Короче они козлы и опять придумывают новую терминологию. Поубивал бы за все эти дебильные CodeDom & Expression trees. Все это сто лет назвад называлось Абстрактное Синтаксическое Дерево (AST).
TK>Собственно preview версия C# 3.0 доступна для делающих — можно будет скачать и, посмотреть что к чему.
Ну, да... Я уже глянул. Вот только не понял как преобразовывать эти самые Expression trees в скомилированный код.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
AVK>С этим и обычные лямбда-функции справяться, никакой необходимости в этом случае в кодогенерации нет. Я тут покумекал и кажется понял зачем они эту штуку ввели. Это нужно чтобы эффективно реализовывать на базе Query Expressions трехзвенные решения. На клиенте просто укатываем запрос в такой expression tree, а на сервере получаем готовый код, который не надо интерпретировать.
Это из серии у гого чего болит. До таких долекоидущих мыслей я даже не додумался.
О несостоятельности данной теории говорит и то, что деревья выражений не реализуют ISerializable и не помечены соотвествующим атрибутом (корочен не сериализуются).
Все же они созданы для метапрогарммирования с трансформацией АСТ и для генерации кода в рантайме.
AVK>Нет, этого не будет. Ты наверное неверно понял что это за штука. Никаких планов там нет, это просто описатель, по которому стандартная библиотека умеет емитом генерить код метода.
В Query ничего не эмитится. А как заэмитить код из деревьев выражений я пока не нашел. Но это точно должно быть возможно.
AVK> Логика там примитивнейшая (скорее всего просто в ресурсах компилятор сохраняет скомпилированный IL-код). Очень вряд ли прикладной программист сможет вмешаться в процесс генерации этого кода. По крайней мере в текущей реализации этого точно нет.
Деревья выражений для того и созданы. Только к запросам это не имеет отношения. Правда можно на них наплевать и генерировать код в рантайме. Возможно что при обращении к БД именно так и делается.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, GlebZ, Вы писали:
VD>>Полностью согласен. Хорошим решением было бы введение макросов в стиле Лиспа или как предложил uw в стиле Nemerle. GZ>Так что там предложил? (Ссылку исправь, пожалуйста).
Здравствуйте, AndrewVK, Вы писали:
AVK>Вот именно что обработка! Здесь же только запрос в select-like стиле.
И? Это самая сложная операция требующая декларативности. А удалять или обновлять это можно предварительно скопировав в отдельный список.
VD>> К тому же это только сахар. Все переписывается в функциональный силь. Так что это встроенный DSL.
AVK>Ключевой момент DSL в том, что его можно менять под предметную область. А здесь ничего менять нельзя. Так что это нифига не DSL.
А работа со списками и есть та самая предметная область.
ЗЫ
Я вобще-то немогу понять почему foreach не вызывает никаких нареканий, а сделаный по его образу и подбию чуть более сложный Query вызывает.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, vdimas, Вы писали:
V>>А Extensions::Crypt разве перекрывает MyCryptoClass::Crypt? Если да — от это дыра
AVK>Нет тут никакой дыры. Не забывай, что это синтаксический сахар.
Имелась ввиду дыра на уровне исходников, когда расширяющий метод подменяет метод класса. Все прояснилось, не подменяет.
Тогда другой вопрос — а если в области видимости находится несколько "расширителей"?
Здравствуйте, vdimas, Вы писали:
AVK>>Нет тут никакой дыры. Не забывай, что это синтаксический сахар.
V>Имелась ввиду дыра на уровне исходников, когда расширяющий метод подменяет метод класса.
Ерунда это. На уровне исходников из компилируемого кода по отношению к другому компилируемому коду можно сделать все. Там не может быть дырки просто потому что для дырки нужно что то, что дыркой не является.
V>Тогда другой вопрос — а если в области видимости находится несколько "расширителей"?
Читай стандарт, пробуй. Какой смысл мне в испорченный телефон играть?
AVK>>Ну, надо признать, что в Delphi.NET похожее уже есть.
VD>Думашь, только в МС читают форумы посвященные стандартизации С++? К тому же уверен, что фишка уже реализована в других языках за долго до того как она попала в Дельфи.
Для Delphi это было необходимо для совместимости старой объектной модели с нетовской. Но эта фишка сразу всем понравилась.
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, AndrewVK, Вы писали:
ceo>>Сейчс идет речь о версии языка. Т.е. выпустят раширение для компилятора и студии. AVK>На сайте сказано что это C# 3.0 (Orkas). Что такое Orkas объяснять надо?
Но, в настоящее время, работает это на текущей версии .NET 2.0 т.е. пока есть только компилятор реализующий нужный сахар.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, Serginio1, Вы писали:
S> Для Delphi это было необходимо для совместимости старой объектной модели с нетовской. Но эта фишка сразу всем понравилась.
Думаю, что "совместимости старой объектной модели с нетовской" была только дополнительным побуждющим фактором. Или их дизайнеров языка зря платят зарплату. Такие изменения дожны серьезно продумываться.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, TK, Вы писали:
TK>Но, в настоящее время, работает это на текущей версии .NET 2.0 т.е. пока есть только компилятор реализующий нужный сахар.
То что компилятор совместим с предыдущим фрэймворком не значит, что нет новго фрэймворка.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Но сам DLinq — это синтаксический сахар который преобразует SQL-подобные выражения в банальный код в функциональном стиле. Вот пример из описания DLinq-я:
Это Linq этим занимается. Задача DLinq по полученному дереву сгенерировать SQL стейтменты которые уже будут передаваться в ADO.NET.
VD>Expression trees же позволяют построить АСТ кода. Упомянутое же АВК объявление — это возможность заставить компилятор вместо МСИЛ-а породить АСТ указанного лямбды.
Именно по этому AST и генерируются SQL запросы
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
TK>Это Linq этим занимается. Задача DLinq по полученному дереву сгенерировать SQL стейтменты которые уже будут передаваться в ADO.NET.
Ну, нельзя делегат в дерево превратить. Дерево нужно иметь зараниее. Так что как я понимаю, это все только дополнительные возможности.
VD>>Expression trees же позволяют построить АСТ кода. Упомянутое же АВК объявление — это возможность заставить компилятор вместо МСИЛ-а породить АСТ указанного лямбды.
TK>Именно по этому AST и генерируются SQL запросы
Ну, так его принимают только отдельные функции. А разные Where и.п. принимают на вход делегаты.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Нет, так не прокатит, там есть вполне определенные правила, когда применяется extension-метод.
Но, конечно, открывается простор для багов, если ПОЗЖЕ в класс добавили метод, ранее введенный extension'ом, но с чуть-чуть другим поведением.
Здравствуйте, VladD2, Вы писали:
TK>>Это Linq этим занимается. Задача DLinq по полученному дереву сгенерировать SQL стейтменты которые уже будут передаваться в ADO.NET.
VD>Ну, нельзя делегат в дерево превратить. Дерево нужно иметь зараниее. Так что как я понимаю, это все только дополнительные возможности.
Что-то ты не правильно понимаешь...
TK>>Именно по этому AST и генерируются SQL запросы VD>Ну, так его принимают только отдельные функции. А разные Where и.п. принимают на вход делегаты.
Кто тебе такое сказал? Есть разные реализации. Одни принимают на вход делегаты а другие Expressions. Те которые принимают Expressions умеют по ним генерировать нормальный SQL
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, Igor Trofimov, Вы писали:
iT>Но, конечно, открывается простор для багов, если ПОЗЖЕ в класс добавили метод, ранее введенный extension'ом, но с чуть-чуть другим поведением. здесь
iT>>Но, конечно, открывается простор для багов, если ПОЗЖЕ в класс добавили метод, ранее введенный extension'ом, но с чуть-чуть другим поведением. GZ>здесь
И если представить, что "раньше" метода Split в классе String не было, а был написан extension с таким методом, который по умолчанию считал разделителем пробел и табуляцию, а потом в классе String появился метод Split, который по умолчанию считает разделителем только пробел, то можно представить себе возможные проблемы.
Перекомпиляция пройдет без ошибок, но скомпилится с "родным" методом String.Split вместо старого StringExt.Split.
И будет работать по-другому.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Serginio1, Вы писали:
S>> Для Delphi это было необходимо для совместимости старой объектной модели с нетовской. Но эта фишка сразу всем понравилась.
VD>Думаю, что "совместимости старой объектной модели с нетовской" была только дополнительным побуждющим фактором. Или их дизайнеров языка зря платят зарплату. Такие изменения дожны серьезно продумываться.
Не дополнительным, а необходимым для облегчения переноса нативных приложений. Понятно, что такой сахар (вызов метода класса, вместо статичесих методов) пришелся всем по вкусу.
Вот их переделки для совместимости. http://www.rsdn.ru/Forum/Message.aspx?mid=548308&only=1
Здравствуйте, mogadanez, Вы писали:
M>именно потому что это не тюпла, а ее имитация. =)) M>настоящая тюпла содержит неименованый кортеж
Именованные, не именованные — это не важно. Важно, что это не полноценный тип. Это все портит. А как вынимать данные не важно. Не именованность в ФЯ мне лично не нравится.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, TK, Вы писали:
TK>Но, в настоящее время, работает это на текущей версии .NET 2.0 т.е. пока есть только компилятор реализующий нужный сахар.
Тем не менее релиз пока планируется в новой студии. Может к тому времени и еще что то добавят. Вот nullable types тоже раньше сахаром были.
Здравствуйте, Serginio1, Вы писали:
S> Не дополнительным, а необходимым для облегчения переноса нативных приложений.
Если бы дело было только в переносе (и не нативных, а, прежде всего, VCLных), то намного проще было бы написать преобразователь навроде R#, благо язык делфей простой.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Serginio1, Вы писали:
S>> Не дополнительным, а необходимым для облегчения переноса нативных приложений.
AVK>Если бы дело было только в переносе (и не нативных, а, прежде всего, VCLных), то намного проще было бы написать преобразователь навроде R#, благо язык делфей простой.
Так или иначе эти преобразования проходят, правда сразу в мсил. Система хэлперов больше подходит для этих преобразований (по сути описывающие действия преобразований) являясь более универсальной .
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Igor Trofimov, Вы писали:
iT>Перекомпиляция пройдет без ошибок, но скомпилится с "родным" методом String.Split вместо старого StringExt.Split. iT>И будет работать по-другому.
IMHO Так это в принципе нормально. Обратный ход, когда объект работает с одним методом, а пользователь с другим методом — по моему хуже. Аргументацию, примерно вижу такой:
1. Клиент может и не представлять, что некоторый namespace переопределяет данный метод. А следовательно, если он использует эту функциональность в совершенно других целях, то это должен быть родной метод. Если он использует синтаксис extension, то он вполне должен представлять что это синтаксический сахар. Просто удобство вызова методов связанных(не родных) с объектом. То есть, никакого обмана.
2. Можно явно вызвать метод extension, но вызвать переопределенный метод объекта нельзя. Тут уже более криминально, поскольку непонятно как можно определить синтаксис вызова родного объекта. А в связи с п.1, то вообще источник ошибок.
Ну например:
static class TestExtensions
{
public static string ToString(this string str){return"Переопределено";}
}
static void Main(string[] args)
{
string sss="sss";
Console.WriteLine(TestExtensions.ToString(sss));//явно вызываем метод расширения
Console.WriteLine(sss.ToString()); //тут вызов родного метода
}
выдаст
Переопределено
sss
Вообще, один способ держать метод с именем существующего это безусловно интерфейсы.
public interface IMyObject
{
String MyMethod();
}
public class MyObject:IMyObject
{
String IMyObject.MyMethod()
{
return"Real My Method";
}
}
static class TestExtensions
{
public static String MyMethod(this MyObject myObject){return"Extension";}
}
class Program
{
static void Main(string[] args)
{
MyObject obj=new MyObject();
Console.WriteLine(obj.MyMethod());
IMyObject iface=new MyObject();
Console.WriteLine(iface.MyMethod());
}
}
выдает
Extension
My Real Method
Мне непонятно другое. Вот разделить статик метод и this — проблемы
public class MyObject
{
static public string MyMethod()
{
return"My Static Method";
}
}
static class TestExtensions
{
public static String MyMethod(this MyObject myObject){return"Extension";}
}
class Program
{
static void Main(string[] args)
{
MyObject obj=new MyObject();
Console.WriteLine(obj.MyMethod());//Error Static member
//'LINQConsoleApplication1.MyObject.MyMethod()' cannot be accessed
//with an instance reference; qualify it with a type name instead
Console.WriteLine(MyObject.MyMethod());
}
}
Или то же самое но с помощью модификаторов доступа.
public class MyObject
{
private string MyMethod()
{
return"My Static Method";
}
}
static class TestExtensions
{
public static String MyMethod(this MyObject myObject){return"Extension";}
}
class Program
{
static void Main(string[] args)
{
MyObject obj=new MyObject();
Console.WriteLine(obj.MyMethod());//Error Static member
//'LINQConsoleApplication1.MyObject.MyMethod()' cannot be accessed
//with an instance reference; qualify it with a type name instead
Console.WriteLine(MyObject.MyMethod());
}
}
В саму спецификацию, все это вписывается(если не выдавать ошибку сразу, а дойти до конца поиска с генерацией расширений, и уже если не найден "корректный" метод генерить ошибку компиляции).
Но возможно виноват пункт 3
3. Код работающий за пределами расширяемого класса, должен корректно работать в самом классе. Действительно, если мы при рефакторинге перенесем процедуру(код процедуры) в класс, разрешим namespace, совсем не факт что она заработает как она работала до этого. Скорее всего, это и есть реальная причина.
Ну и последнее, это из спецификации(там это написано красным, чтобы было видно):
Extension methods are less discoverable and more limited in functionality than instance methods. For those reasons, it is recommended that extension methods be used sparingly and only in situations where instance methods are not feasible or possible.
Здравствуйте, TK, Вы писали:
>> А зачем они делегат Func (из System.Query) назвали сокращённо? >> Есть же прекрасное слово Function
TK>А еще есть прекрасное слово "анонимный делегат". А то, понапридумывали TK>каких-то стрелочек...
До этого, если не ошибаюсь, в именах типов не встречались сокращения (не путать с аббревиатурами).
Давай тогда и IsolatedStorageFileStream преобразуем в IsltStrgFileStrm
Здравствуйте, GlebZ, Вы писали:
_FR>>А зачем они делегат Func (из System.Query) назвали сокращённо? Есть же прекрасное слово Function _FR>>Надеюсь, поправят GZ>Поправляю. Судя по всему ты не любишь Visual Basic. Там уже давно забили это слово под себя.