В качестве основной цели задекларированна поддержка функционального стиля. 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), но чего то вечером пример придумать не могу. Ну разве что такую лямбду можно будет сериализовать (к примеру, чтобы сохранить в БД или передать по сети).
Здравствуйте, 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 это очень уместно. К тому-же обычно такие запросы можно оптимизировать. Возможно это будет редактируемый план выполнения.
AVK>2) Расширяющие методы (Extension methods). Хитрая штука. Позволяет объявлять статические методы с параметром this и привязывать их в качестве метода экземпляра к существующим классам.
О! Это здорово! Это то, что в Delphi последней назвается helper-классом.
AVK>Любители функционального стиля будут довольны. Хотя возможность творить на этой базе извраты (особенно если совместно с дженериками) меня пугает.
Мда, извраты с печальными результатами (что без поллитры не разберешься) мы уже видели для C# 2.0.
AVK>5. Анонимные типы. Проистекают из возможностей в п.1 и п.4. На основании объектного инициализатора выводится тип.
Что-то вроде tuples.
AVK>7. Выражения запроса. (Query expressions). В новый язык добавлены декларативные конструкции, похожие на SQL.
Здравствуйте, 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>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, 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>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, 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>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, 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 виходят одновременно. Сейчс идет речь о версии языка. Т.е. выпустят раширение для компилятора и студии.
Здравствуйте, 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>ИМХО изврат редкостный. Насколько это будет полезно я пока ответить затрудняюсь.
Учитывая, что работать это будет не только с базами данных, но и с любой коллекцией то, достаточно полезно.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, Аноним, Вы писали:
А>Флеш-моб может устроить ? Всем россиянам, кто будет принимать участие — явиться в шапках-ушанках с бутылкой водки в кармане и с карманным медведем на поводке
Что-то я вас в упор не вижу
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, 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>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, 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>