Extensions с generic'ами не живут, что в общем, понятно, но обидно:
static class ListExt<T>
{
public static string First(this List<T> list)
{
return list[0];
}
public static string Last(this List<T> list)
{
return list[list.Count-1];
}
}
...
var list = new List<string> {"aaa", "bbb", "ccc"};
Console.WriteLine(list.First()); // А вот тут хочется extension-свойств!
Не пашет такая попыточка. Хотя вообще-то принципиально это можно было бы сделать.
Всего лишь превращать list.First() не в ListExt<T>.First(list), а в ListExt<string>.First(list), гладя на совпадающее количество type-args.
static class ListExt
{
public static T First<T>(this List<T> list)
{
return list[0];
}
public static T Last<T>(this List<T> list)
{
return list[list.Count-1];
}
}
Параметризировать надо конкретный метод а не класс.
(В предыдущем сообщении у меня вообще string затесался откуда-то )
До сих пор не хватает "красивой" работы с нулевыми значениями
сейчас вместо:
if (Root.Config.User.Age > 16)
{
//bla-bla
}
часто приходиться писать:
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
}
т.е. хочеться иметь оператор вида '.?', который возвращает нуль, если левая часть имеет нулевое значение
if (Root.?Config.?User.?Age > 16)
{
//bla-bla
}
или может даже лучше:
if (Root?.Config?.User?.Age > 16)
{
//bla-bla
}
Особенно это нужно при описании правил бизнес логики, т.к. в бизнес-логики часто мы имеем на руках только частичную информацию о мире
Здравствуйте, DarkGray, Вы писали:
DG>До сих пор не хватает "красивой" работы с нулевыми значениями
DG>т.е. хочеться иметь оператор вида '.?', который возвращает нуль, если левая часть имеет нулевое значение
DG>
Первое всё-таки лучше.
DG>Особенно это нужно при описании правил бизнес логики, т.к. в бизнес-логики часто мы имеем на руках только частичную информацию о мире
Пусть Root == null. Ты предлагаешь, чтобы ((RootClass)null).?Config тоже вычислялось в null? А во что же должно вычисляться все выражение Root.?Config.?User.?Age. В 0 (ноль)? И тип у него естественно будет int?
Дык, возраст со знаением ноль и возраст с неизвестным значением — это ведь две разные вещи.
А если тип будет, например, строка? возвращать пустую строку? А если структура?
Сколько народу ругается на Oracle, где пустая строка и NULL — это одно и тоже!
ИМХО, нужно вводить специальные типы, по анаголии с NULL концепцией в SQL. Так чтобы переменная этого типа могла кроме определенного знаения хранить еще и признак наличия значения, т.е. попросту говоря могла бы не иметь значения. И соответственно вводить специальные операции с такими типами.
Я в своем DSL, основа которого была нагло стырена с C#, ввел такие типы. null оставил как есть в C#, а в дополнение к этому ввел константу undefined (типа <undefined>, как и null в C# имеет специальный тип <null>).
int x = 0; // Обыный int.int% y = 0; // Как я его назвал - undefinable int.if (defined y) // Пройдет. Аналогия с SQL-ым IS NULL.
...;
y = undefined;
if (y == undefined) // Не пройдет. Так как undefined != undefined, как в SQL.
...;
x = (int)y; // Требуется явное приведение. В ран-тайм будет ошибка.
y = y + x; // Выполнится как y + (int%)x. Получится undefined.
Это для простых типов. Теперь про классы с полями и свойствами:
class A
{
public B% b;
}
class B
{
public int x;
}
A% a = new A();
a.b = undefined;
int% y = a.b.x; // y будет undefined. Так как a.b - undefined.
// Несмотря на то, что поле x имеет тип int,
// операция ((B%)somevar).x имеет тип int%.
// но только на чтение.
a.b.x = 7; // В ран-тайм будет ошибка. На запись a.b.x
// имеет тип int.
Также работают свойства и индексеры.
Дык вот о птичках. Вроде в C# уже ввели работу с SQL-like типами. Там вроде какой-то стандартный дженерик есть, не помню как он там называется. С помощью такого дженерика и перегрузки операторов конечно можно имитировать работу с примитивными SQL-like типами.
А вот с полями и свойствами так как я показал — фигушки...
Если бы был мощный препроцессор, можно быть бы написать универсальный макрос, принимающий конструкцию `a.b.c.*.z`, проверяющий каждый член на null и возвращающий некое значение по умолчанию в таком случае. Но вот этого в C# что-то не предвидится.
Здравствуйте, stalcer, Вы писали:
S>Здравствуйте, DarkGray, Вы писали:
DG>>т.е. хочеться иметь оператор вида '.?', который возвращает нуль, если левая часть имеет нулевое значение
S>Интересная идея.
DG>>
S>Пусть Root == null. Ты предлагаешь, чтобы ((RootClass)null).?Config тоже вычислялось в null? А во что же должно вычисляться все выражение Root.?Config.?User.?Age. В 0 (ноль)? И тип у него естественно будет int? S>Дык, возраст со знаением ноль и возраст с неизвестным значением — это ведь две разные вещи. S>А если тип будет, например, строка? возвращать пустую строку? А если структура?
S>Сколько народу ругается на Oracle, где пустая строка и NULL — это одно и тоже!
Я думаю, необязательно именно возвращать NULL. Можно, например, просто выходить без исключения из условного оператора, так как условие заранее не выполнено.
FDS>Я думаю, необязательно именно возвращать NULL. Можно, например, просто выходить без исключения из условного оператора, так как условие заранее не выполнено.
Где не обязательно возвращать? Какой порядок выисления выражений то?
S>>Какого типа каждое из этих промежуточных выражений? FDS>CObject
Ну-ну. А разве CObject имеет поле Config? А? Или может быть поле User. Или может быть CObject можно сравнивать с int (c 16)? Чушь!
FDS>Root.Config инициализированно? — нет — выйти из условного оператора
FDS>Root.?Config.?User инициализированно? — аналогично
if (!(Root.?Config.?User.?Age > 16))
...;
if ((Root.?Config.?User.?Age > 16) || someBoolVar)
...;
bool x = (Root.?Config.?User.?Age > 16);
Здравствуйте, FDSC, Вы писали:
FDS>Компилятор должен обрабатывать примерно так: FDS>Root.Config инициализированно? — нет — выйти из условного оператора FDS>Root.?Config.?User инициализированно? — аналогично
Людям явно не нравится механизм обработки исключений и они ощут альтернативы
Здравствуйте, Кодёнок, Вы писали:
Кё>Людям явно не нравится механизм обработки исключений и они ощут альтернативы
А при чем здесь исключения. null есть только для ссылочных типов. А, например, возмем структуру Address. Пусть адрес может быть не задан по условию задачи. И что? Придется заводить еще и булевый признак? Не зря же в SQL сделали NULL. Да и не только в SQL.