Re: О nullable-типах и операторе "? :"
От: Mab Россия http://shade.msu.ru/~mab
Дата: 14.01.06 17:25
Оценка: 35 (2)
Здравствуйте, VladD2, Вы писали:

Я не могу объяснить это поведение с точки зрения доступной мне версии спецификации ECMA. Однако вот цитата из http://download.microsoft.com/download/e/3/8/e38818ae-31e5-462b-b9ad-e6d3cd6ad7c1/Breaking%20Changes%20Beta2%20to%20RTM.doc:

Operator "is" Returns true for T and Non-null T?

The semantics of the is operator have been changed according to Nullable<T> boxing and unboxing changes. The following two examples equate to true when x is either T or a non-null T?. Otherwise, each example equates to false.

// true when x is T or a non-null T?; otherwise, false.x is T?
// true when x is T or a non-null T?; otherwise, false
x is T
Given the following initialization of x, y, and z, the Boolean values for b1, b2, b3, and b4 are determined as shown in the following example:
//

[c#]
int? x = null;
int? y = 10;
int z = 10;

// False; x is boxed as null, null is
// always false.
bool b1 = (x is int?);

// True; y is boxed as int, new behavior
// ensures this is true.
bool b2 = (y is int?);

// True; z is boxed as int, same as b2
// (cannot differentiate).
bool b3 = (z is int?);

// True; y and z are boxed as int, ordinary
// check applies.
bool b4 = (y is int) && (z is int);


Похоже тееперь в MS считают преобразования между T и T? разновидностью боксинга. С другой стороны, спецификация выделяет такие преобразования в отдельный класс (см. 13.7.2 Nullable conversions), к боксингу отношения не имеющий.

Кстати, еще один прикол, взятый отсюда: http://blogs.msdn.com/abhinaba/archive/2005/12/14/503533.aspx
int i = 5;
if ( i == null )
  Console.WriteLine ("null");
if ( 5 == null )
  Console.WriteLine ("null");

VS2005 считает такой код корректным (а вот Решарпер не считает, о чем уже оформлен соответствующий баг )
Re[4]: О nullable-типах и операторе "? :"
От: Алексей.  
Дата: 14.01.06 17:36
Оценка: 25 (1)
Здравствуйте, VladD2, Вы писали:

VD>Однозначен то он однозначен. Но это же требует LL(*)-парсера.

VD>Мне нужно азрулить ситуацию на CocoR который строит только LL(1)-парсеры с возможностью ручного заглядывания вперед (хоть до посинения).

VD>Так вот у меня есть варианты:

VD>1. Попытаться распознать выражение идущее за "?". Если выражение распознается и за ним идет ":" мы имеем дело с оператором "?:" и дело в шляпе. Если нет, то принимаем решение, что "?" — это часть определения типа.
VD>Так вот проблема в том, что ручной анализ выражения — это застрелиться .
VD>2. Придумать некую эвристику (наподобии той, что применяется для разруливания неоднозначностей с "F(G<A, B>(7));".
VD>В общем, первый способ конечно надежен, но сложен и медленнен.
VD>Между тем, описанная неоднозначность возникает только в случае применения оператора "is" в сочетании с нулбл-типами и/или оператором "?:".
VD>Вот и хотелось бы попытаться определить эвристику по которой можно было бы ограничиться проверкой некоторого набора лексем.
VD>Ведь если пойти логически, то если после "?" следуют: ")", "=", "?" (возможно что-то еще), то "?" точно являетс частью определения типа.
VD>Вот и хотелось бы попытаться продумать набор таких предположений и проверить не возникает ли при этом каких-то проблем.

У меня получился такой список:
если после '?' идет одно из:

. -> = += -= *= /= %= &= |= ^= <<= >>= ? ?? || && | ^ != == as is >= <= > < >> << % /

то '?' являются частью типа.

если одно из:

+ — & * ( ++ --

то, увы придется делать попытку разбора последовательности токенов как выражение, и проверить следующее за выражением токен. Если он ':', то '?' является частью условного выражения. В противном случае частью типа.
Re[4]: О nullable-типах и операторе "? :"
От: Воронков Василий Россия  
Дата: 14.01.06 20:38
Оценка:
Здравствуйте, VladD2, Вы писали:

Мелькает еще одна мысль, только непонятно есть в ней прок или нет.
Как я понимаю, в выражении i is int? значок "?" является частью _названия_ типа.Соответственно, получаем:

bool b = i is int?; //валидно
bool b = i is int ?; //невалидно

может, получится как-нибудь хитро разруливать это на этапе проверки имени типа?
Re[5]: О nullable-типах и операторе "? :"
От: Mab Россия http://shade.msu.ru/~mab
Дата: 14.01.06 20:43
Оценка: 10 (1) +1
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Как я понимаю, в выражении i is int? значок "?" является частью _названия_ типа.Соответственно, получаем:
Ну ты бы попробовал компилировать свои примеры хотя бы перед тем как писать Знак вопроса и int -- два отдельных токена. Есть между ними пробел или нет -- без разницы.
Re[6]: О nullable-типах и операторе "? :"
От: Воронков Василий Россия  
Дата: 15.01.06 01:30
Оценка: +1
Здравствуйте, Mab, Вы писали:

Mab>Здравствуйте, Воронков Василий, Вы писали:

ВВ>>Как я понимаю, в выражении i is int? значок "?" является частью _названия_ типа.Соответственно, получаем:
Mab>Ну ты бы попробовал компилировать свои примеры хотя бы перед тем как писать Знак вопроса и int -- два отдельных токена. Есть между ними пробел или нет -- без разницы.

А может у меня компилилки нету
Re[3]: О nullable-типах и операторе "? :"
От: Smarty Россия  
Дата: 15.01.06 02:00
Оценка:
Здравствуйте, mormat, Вы писали:

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


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


VD>>>Плюс смущает, что "i is int?" вообще компилируется. Ведь i имеет тип int, а не int?. Это случаем не баг?


A__>>Так же, как компилируется i is object, i is SomeType и проч. зачем тогда вообще нужен is? Я понимаю, четыре часа ночи...


M>VladD2 хотел сказать, что если

M>
M>            int i;
M>            Console.Write( i is int? );
M>

M>или
M>
M>            int? i;
M>            Console.Write( i is int );
M>

M>то в обоих случаях на экран вылезет true. И это действительно странно, ибо

Это абсолютно НЕ странно ибо:
Преобразование int/int? однозначно есть в обе стороны.
Re[2]: О nullable-типах и операторе "? :"
От: Smarty Россия  
Дата: 15.01.06 02:00
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>Похоже тееперь в MS считают преобразования между T и T? разновидностью боксинга. С другой стороны, спецификация выделяет такие преобразования в отдельный класс (см. 13.7.2 Nullable conversions), к боксингу отношения не имеющий.

По-моему заместо заумной фигни с боксингами одна фраза

An is expression evaluates to true if the provided expression is non-null, and the provided object can be cast to the provided type without causing an exception to be thrown.

легко и элегантно объясняет результаты по всем 4м буллам....

Mab>VS2005 считает такой код корректным (а вот Решарпер не считает, о чем уже оформлен соответствующий баг )

Не совсем. Соотв. ворнинг генерится. Возможно вместо ворнинга еррор должен быть, но это уже узко-техничесикй вопрос...
О nullable-типах и операторе &quot;? :&quot;
От: Аноним  
Дата: 14.01.06 01:55
Оценка: :)))
> Console.WriteLine(i is int? "+" : "-"); Надо заглядывать вперед анализируя наличие ":"?

лучше поставить скобки
(i is int) ? "+" : "-"

если i надо проверить на принадлежность к nullable-типу, то так
(i is int?) ? "+" : "-"
но можно и так
i is int? ? "+" : "-"


---
см.: TaskRunner, PopupWindow, Html2XmlConverter, Win32ResourceManager, MenuBuilder, Lens .


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[2]: О nullable-типах и операторе &quot;? :&quot;
От: Аноним  
Дата: 14.01.06 15:11
Оценка:
>Или это ошибка компилятора.
Или горе от ума очередное.
В vb.net конструкция наподобие этой

        Console.WriteLine(TypeOf i Is Integer)
        Console.WriteLine(TypeOf i Is Test(Of Integer)()) ' а тут false
        Console.WriteLine(TypeOf i Is Nullable(Of Integer))


вовсе не существует — слева от Is может быть только ссылочный тип.

Ну, и оператора "?" вместе с синтаксисом int? — тоже нету.
Все на VB.NET!!!
----
В моём WMP Плагины для Офиса


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[2]: О nullable-типах и операторе &quot;? :&quot;
От: Аноним  
Дата: 14.01.06 15:34
Оценка:
Странно что вы тут не упомянули Оберон и сингулярность альфа-проксимити.

Открываю МСДН. И ба!! Что я вижу!

is (C# Reference)
Checks if an object is compatible with a given type...
. . .
An is expression evaluates to true if ... object can be cast to the provided type without causing an exception to be thrown


Запускаем студию (без поключения нейтринного квазигенератора) при помощи мышиного клика и пишем.
            int i = 0;
            int? ni;
            ni = (int?)i;


ошибки не возникает.

Лучшее — враг хорошего (C) Вольтер


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[3]: О nullable-типах и операторе &quot;? :&quot;
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.06 06:13
Оценка: :)
Здравствуйте, Dkm_S, Вы писали:

D_S>Ну, и оператора "?" вместе с синтаксисом int? — тоже нету.


Это, несомненно, радует. Но огорчает слишком много других наворотов. Все же как было здорово писать на VB 1-4. Правда?

D_S>Все на VB.NET!!!


Да, да. Нечего здесь ошиваться. Все на Выбенет! .
... << RSDN@Home 1.2.0 alpha rev. 628>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: О nullable-типах и операторе &quot;? :&quot;
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.01.06 06:13
Оценка:
Здравствуйте, Poluekt, Вы писали:

P>Запускаем студию (без поключения нейтринного квазигенератора) при помощи мышиного клика и пишем.

P>
            int i = 0;
P>            int? ni;
P>            ni = (int?)i;


P> ошибки не возникает.


Ну, тогда объясни почему это не работает в этом случае:
Re[2]: О nullable-типах и операторе "? :"
Автор: VladD2
Дата: 14.01.06
... << RSDN@Home 1.2.0 alpha rev. 628>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: О nullable-типах и операторе "? :"
От: Mab Россия http://shade.msu.ru/~mab
Дата: 15.01.06 08:07
Оценка: +1
Здравствуйте, Smarty, Вы писали:

S>По-моему заместо заумной фигни с боксингами одна фраза

S>

S>An is expression evaluates to true if the provided expression is non-null, and the provided object can be cast to the provided type without causing an exception to be thrown.

S>легко и элегантно объясняет результаты по всем 4м буллам....

1. Насколько я понимаю, это фраза из C# Programmer's Reference. По статусу это всего лишь некие сопроводительные комментарии, а никак не спецификакиция. Мы же здесь обсуждаем стандарт ECMA-334.

2. Если ты считаешь, что эта фраза сама по себе способна что-то объяснить, то ошибаешься. Скажем, при вычислении operator is не учитываются explicit user-defined conversions.

3. В том же Programmer's Rereference в самом конце еще написано:

Note that the is operator only considers reference conversions, boxing conversions, and unboxing conversions. Other conversions, such as user-defined conversions, are not considered.

Мягко говоря, это не тот стиль, которым описывается стнандарт языка (note that совершенно не уместен). В любом случае, ECMA-334 не считает преобразование от int к int? разновидностью боксинга.

Проблема скорее всего в том, что готовой версии стандарта нет. То, что я сейчас смотрю -- это 3rd Edition/June 2005. Вместе с VS2005 Release идет некий doc-файл, озаглавленный C# Language Spec 2.0, представляющий собой дополнение к спецификации 1.2. В этом файле есть раздел 20.8.4 (никак не коррелирующий с таковым в ECMA -- нумерация тут другая):

The is operator (§7.9.9) is extended to support nullable types. An operation of the form e is T, where e is an expression and T is a type, is evaluated as follows, after type arguments have been substituted for all type parameters:
• If the type of e is a reference type or a nullable type and the value of e is null, the result is false.
• Otherwise, let D represent the dynamic type of e as follows:
o If the type of e is a reference type, D is the run-time type of the instance reference by e.
o If the type of e is a nullable type, D is the underlying type of that nullable type.
o If the type of e is a non-nullable value type, D is the type of e.
• The result of the operation depends on D and T as follows:
o If T is a reference type, the result is true if D and T are the same type, if D is a reference type and an implicit reference conversion from D to T exists, or if D is a value type and a boxing conversion from D to T exists.
o If T is a nullable type, the result is true if D is the underlying type of T.
o If T is a non-nullable value type, the result is true if D and T are the same type.
o Otherwise, the result is false.

Жирным выделены пункты, обяъсняющие поведение компилятора.
Re[4]: О nullable-типах и операторе &quot;? :&quot;
От: Mab Россия http://shade.msu.ru/~mab
Дата: 15.01.06 08:13
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>Ну, тогда объясни почему это не работает в этом случае:
VD>Re[2]: О nullable-типах и операторе "? :"
Автор: VladD2
Дата: 14.01.06

Влад, что именно не работает? Не получается объявить свой тип, ведущий себя как Nullable<T>? Факт, не получается и не получится.

Кстати, в ранних версиях 2005 этот самый Nullable<T> был вполне обычным типом. Но вот начиная с August CTP в дизайне произошли серьезные изменения: он стал частью рантайма и учитывается, например, при боксинге специальным образом. Подробнее можно почитать здесь:
http://blogs.msdn.com/somasegar/archive/2005/08/11/450640.aspx
С точки зрения компилятора этот Nullable<T> тоже не обычный тип. Один из множества примеров: посмотри на lifted conversions. Для своих типов устроить такое ты не сможешь.
Re[5]: О nullable-типах и операторе "? :"
От: mihailik Украина  
Дата: 15.01.06 08:23
Оценка: 9 (1)
VD>Зачем встроена поддержка в джит, понятно. Это сделано для эмуляции красобы при работе с боксингом.

Ты шире взгляни. Это сделано для удобства работы программиста с Nullable.


VD>А вот химия компилятора не очень очевидна.


Да, в общем, за тем же. Для удобства программиста.

Похоже, при разработке C# 2.0 у них вообще поменялась внутренняя установка. Простота реализации компилятора больше их не волнует, главное преимущества языка/платформы для разаработчика. Смотри, сколько инфраструктурных багов нашли...

Вон, даже non-verifiable можно получить без ключа /unsafe, а они это за серьёзную ошибку не считают. Видно, зашиваются совсем по времени. Кстати, и Эрик Ганнерсон дёрнул в сторону именно на этапе C# 2.0, почуял неладное что ли?
Re[5]: О nullable-типах и операторе "? :"
От: Алексей.  
Дата: 16.01.06 08:18
Оценка:
А>если одно из:

А>+ — & * ( ++ --


MSVC# во всех этих случаях не считает '?' частью типа. Что в общеим логично, учитывая что все они имеют более высокий приоритет чем оператор приведения as.
Re[6]: О nullable-типах и операторе "? :"
От: Алексей.  
Дата: 16.01.06 08:38
Оценка:
Вот еще один пример:

void f()
{
    int a = 0;
    int b = a is int + a is int; // int b = ( ( a is int ) + a ) is int;
    int b = a is int? + a is int; // int b = ( a is int ) ? ( ( + a ) is int ); error: expected ':'
}

Или вот (проблема кочующего ':'):

void f()
{
    int a = 0;
    int b = a is int? + a is int? + a : a;
}
Re: О nullable-типах и операторе "? :"
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.01.06 14:07
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Что-то я не въеду в принципы по которым компилятор должен отличать nullable-тип и оператор "? :".

VD>Например:
VD>
VD>int i = 0;
VD>Console.WriteLine(i is int?);
VD>Console.WriteLine(i is int? "+" : "-");

А еще бывает
Console.WriteLine(i is int ? ? "+" ?? "*" : "-");

1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: О nullable-типах и операторе "? :"
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.01.06 14:07
Оценка:
Здравствуйте, Mab, Вы писали:
Mab>Жирным выделены пункты, обяъсняющие поведение компилятора.
Кстати, по поводу стандарта. Я тут напоролся на то, что вот в таком контексте
Nullable<SomeType> a;
SomeOtherType b;
выражение a + b имеет тип Nullable<SomeType>, если есть соответствующий перегруженный оператор +, возвращающий SomeType.
Пример:
int? a = 5;
int b = 5;

Выражение a+b не только компилируется без ошибок, но и имеет тип int?, несмотря на отсутствие оператора + c соответствующими аргументами. Еще больше я удивился, когда увидел работоспособность выражения
(TimeSpan.FromDays(1)+(DateTime?)Now).HasValue;

Это у меня глюки, или компилер еще умнее, чем я ожидал?
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: О nullable-типах и операторе "? :"
От: Mab Россия http://shade.msu.ru/~mab
Дата: 16.01.06 14:16
Оценка: 88 (2)
Здравствуйте, Sinclair, Вы писали:
S>Это у меня глюки, или компилер еще умнее, чем я ожидал?
Все совершенно правильно. Это т.н. lifted operators плюс (nullable conversions, позволяющие поднять int до int?):

14.2.7 Lifted operators
Lifted operators permit predefined and user-defined operators that operate on non-nullable value types to
also be used with nullable forms of those types. Lifted operators are constructed from predefined and userdefined
operators that meet certain requirements, as described in the following:
• For the unary operators
+ ++ — -- ! ~
a lifted form of an operator exists if the operand and result types are both non-nullable value types. The
lifted form is constructed by adding a single ? modifier to the operand and result types. The lifted operator
produces a null value if the operand is null. Otherwise, the lifted operator unwraps the operand, applies the
underlying operator, and wraps the result.
...

Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.