[Этюд, C#] Cast expression
От: nikov США http://www.linkedin.com/in/nikov
Дата: 12.04.11 18:55
Оценка: 127 (8)
class C
{
    unsafe static void Main()
    {
        var x = (global::C) -1;
        var y = (global::System.Int32) -1;
        var z = (global::System.Int32*) -1;
    }
    
    public static implicit operator C(int x)
    {
        return null;
    }
}


Скомпилируется ли эта программа? Если нет, то какие будут ошибки?
Re: [Этюд, C#] Cast expression
От: Пельмешко Россия blog
Дата: 12.04.11 21:45
Оценка: 176 (9)
Здравствуйте, nikov, Вы писали:
N>
N>class C
N>{
N>    unsafe static void Main()
N>    {
N>        var x = (global::C) -1;
N>        var y = (global::System.Int32) -1;
N>        var z = (global::System.Int32*) -1;
N>    }
    
N>    public static implicit operator C(int x) { return null; }
N>}


N>Скомпилируется ли эта программа? Если нет, то какие будут ошибки?


Не скомпилируется, отвалится строка (шок):

var y = (global::System.Int32) -1;

Смотрим правила разрешения неоднозначностей в cast expressions:

To resolve cast-expression ambiguities, the following rule exists: A sequence of one or more tokens (§2.3.3) enclosed in parentheses is considered the start of a cast-expression only if at least one of the following are true:

• The sequence of tokens is correct grammar for a type, but not for an expression.
• The sequence of tokens is correct grammar for a type, and the token immediately following the closing parentheses is the token “~”, the token “!”, the token “(”, an identifier (§2.4.1), a literal (§2.4.4), or any keyword (§2.4.3) except as and is.

Так вот, последовательность токенов global::System.Int32 является корректной с точки зрения грамматики, но при этом может означать и тип, и выражение (например, статическое поле Int32 класса System). Второе правило тоже не катит, так как после закрывающей скобки не идут токены “~”, “!”, “(” либо идентификаторы, литералы или ключевые слова (кроме as и is). Стоп! -1 разве не литерал? Оказывается, что с точки зрения C# — нет, это не literal expression, это унарное выражение отрицания литерала 1!

В итоге C# не будет считать выражение приведением типов и будет ругаться на непонятное использование имени типа lobal::System.Int32 в выражении.

var z = (global::System.Int32*) -1;

Тут срабатывает первое правило — последовательность токенов global::System.Int32* корректна и в C# может означать только тип, не выражение (так как global::System.Int32* — это и не умножение, и не pointer inderection (префиксная унарная операция)). И абсолютно не важно что там после закрывающей скобки.

var x = (global::C) -1;

Тут тоже первое правило — последовательность токенов global::C может являться корректной записью типа, но не выражения ("внутри" пространства имён global, как и любого другого, не могут содержаться значения).

Re[2]: [Этюд, C#] Cast expression
От: nikov США http://www.linkedin.com/in/nikov
Дата: 12.04.11 21:53
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>[skipped]


Как всегда, абсолютно правильный анализ!
Re: [Этюд, C#] Cast expression
От: hardcase Пират http://nemerle.org
Дата: 13.04.11 06:13
Оценка: :))
Здравствуйте, nikov, Вы писали:

N>Скомпилируется ли эта программа? Если нет, то какие будут ошибки?


Спасибо! Теперь будет во что ткнуть вопрошающих "почему у вас указание типа не как в кавайной Сишечке".
http://nemerle.org/Banners/?t=Developer!&g=dark /* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: [Этюд, C#] Cast expression
От: Константин Л. Россия  
Дата: 14.04.11 08:20
Оценка: +1 :)
Здравствуйте, Пельмешко, Вы писали:

[]

Estuve en Granada y me acorde' de ti
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.