С# 3.0
В query expression сделали from до select -- ура.
from c in customers
orderby c.Country, c.Balance descending
select new { c.Name, c.Country, c.Balance }
переводиться в
customers.
OrderBy(c => c.Country).
ThenByDescending(c => c.Balance).
Select(c => new { c.Name, c.Country, c.Balance })
При этом лямбда выражения могут преобразовываться в делегаты, либо в структуры данных. Первый вариант скорее всего будет реализовываться коллекциями, второй ADO, когда выражения будут преобразовываться в SQL.
Из ФЯ много удобных фишек надергали.
частично поддержку open OOP добавили.
поддержку запросов в язык добавили.
до сих пор не хватает:
"красивой" работы с null-ем
продвинутой работы с исключениями
Да прикольно! Почти все что было в COmega перешло в C# 3 получается какой-то салат из C#, SQL и XML VB 9.0 они тоже таким же образом хотят извратить.
А что ты хочешь для исключений?
Dim CountriesWithCapital As XElement = _
<Countries>
<%= Select <Country Name=(Country.Name)
Density=(Country.Population/Country.Area)>
<Capital>
<Name><%= City.Name %></Name>
<Longitude><%= City.Longitude %></Longtitude>
<Latitude><%= City.Latitude %></Latitude>
</Capital>
</Country> _
From Country In Countries, City In Capitals _
Where Country.Name = City.Country %>
</Countries>
<Text>Hello</Text>
</Form>).ShowDialog;
Интересно, что в VB идет сначала Select -- типа VB прогеры мыслят сначала "что", а потом "как", а C# прогеры наоборот
На самом деле за всеми этими XML и SQL компилятор генерит просто О*УЕННО много кода (хотя бы в той же comegb)
new From { Text = "Hello" } .ShowDialog;
Может они научат компилятор для одного и того же лямбда выражения использовать один код.
конечно, мало.
хочется именно "красивую" обработку нулевых значений
вот допустим мы хотим написать:
if (Root.Config.User.Age > 10)
{
//bla-bla
}
в реальности мы должны писать (даже в 3.0) что-то такое:
int? age = null;
var root = Root;
if (root != null)
{
var config = root.Config;
if (config != null)
{
var user = config.User;
if (user != null)
age = user.Age;
}
}
if (age != null && age.Value > 10)
{
//bla-bla
}
в 2.0 еще хуже, т.к. вместо var - приходится везде прописывать длиннющие типы.
в С# 3.0 есть extension methods, когда сатические методы представляются как методы экземпляра.
class X
{
public static User Config(Root root) { ... }
}
тогда
root.Configбудет
X.Config(root)
может и для свойств такую штуку сделают
хочется работать с информацией о выполнении/сдыхании какого-то участка кода так же просто, как и со всем остальным
но, по идее, это можно обойти через anonymous delegate-ы, так что это не критично.
вообще, хочется что-то такого:
try(ReadFromServer || try(ReadFromCache || try(GenerateDummy;
где соответственно сначала пытаемся прочитать данные сервера, если не получается, то пытаемся взять из кэша, иначе генерим заглушку.
также хочется, что если сдохли все три варианта - то получить совокупное исключение, в котором отражено - какое из исключений было кинуто каждым из вариантов.
да
потому, что иначе - выражения для бизнес-логики получаются очень и очень страшными, т.к. в бизнес-логике часто нормально, что у нас на руках неполная информация о мире.
class X{ public static User Config(this Root root) { ... }}
1) это иметь возможность получить список всех текущих параметров функции (для трассировки часто такое надо)
т.е. хочется закопипастить в каждую функцию один и тот же код вида
Tracer.TraceMethod(@args);
и дальше об этом не думать.
2) иметь возможность получить номер итерации в foreach
например:
StringBuilder str = new StringBuilder;
foreach (int i in items)
{
str.Append("{");
str.Append(i);
str.Append("}");
if (@iteration > 0)
str.Append(", ");
}
или та же беготня по двум совместным коллекциям
v.Hello 'Dynamic Interface
v.("Hello") 'Dynamic Identifier
при этом в типе v нет метода Hello
и чем это поможет? руками генерить для каждого поля его эквивалент, который возвращает null?
так почти такое, я и сейчас могу.
2) на этот точно не согласятся -- не так сложно самому итерации считать.
самих значений, в рефлекшене же не будет.
[nullable] class User {
public string Name { ... }
}
генерирует
namespace NullableDot {
class BlaBla121324 {
public static string get_Name(this T? user) { return user.HasValue ? user.getName : null; }
}
}
Про аргументы понял.
customers.
Where(c => c.City == "London").
SelectMany(c =>
c.Orders.
Where(o => o.OrderDate.Year == 2005).
Select(o => new { c.Name, o.OrderID, o.Total })
)
применение аттрибутов - почти всегда обозначает плохое решение, т.к. внешняя по сути информация - засовывается внутрь типа.
зы
аттрибутами нельзя пометить чужой код
через аттрибуты нельзя сделать несколько разных вариантов
аттрибуты - увеличивают связность кода
для статик расширений - this точно может быть нулем?
1) оператор типа .?
2) @args
3) extention properties (а то эти гады делают extention methods скорее всего, чтобы прикручивать всякие where select методы к существующим классам, поэтому могут и забить на свойства)
4) еще раз new(...) -- Я в свое время попросил, чтобы в ограничении дженериков кроме new можно было указывать параметры, т.к. дефолтные конструкторы не совсем цивильно. Так мне тогдашний ПМ сказал, что это усложнит синтаксис, а они хотя остатить его простым. Может для 3.0 уже прокатит
думаю да -- это ж все делается во время компиляции, получается вызов статического метода, а там все равно, что пихают.
Оставить комментарий
bastii
Ну как, что скажите.Вот тут спецификация.