Продолжаю непонимать C#. Теперь про операторы.
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 25.05.05 17:10
Оценка:
Привет всем.

Вопрос из серии "Помогите РеШарперу"

Вопрос: почему компилируется код

enum E{A}

....
E e = E.A
IntPtr ptr = (IntPtr)e;


Если совсем конкретно — то почему компилируется выделенный cast.

Поясню вопрос: в стандарте языка C# параграф 6.4.3 сказано, что при вызове explicit conversion оператора его параметр должен преобразовываться неявно.

В IntPtr есть explicit operator IntPtr(int). В enum'е операторов нет. Enum к int'у неявно не приводится.

Более того, если написать что-то типа


struct S
{
  public static explicit operator S (int i) {....}
}


То выражение

S s = (S) e;


не скомпилируется.
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re: Продолжаю непонимать C#. Теперь про операторы.
От: Mab Россия http://shade.msu.ru/~mab
Дата: 25.05.05 17:56
Оценка:
Очень похоже на баг в компиляторе. Ну или как минимум несоответствующее спецификации поведение с enum-types
(еще одно, мы уже обсуждали).

X>В IntPtr есть explicit operator IntPtr(int). В enum'е операторов нет. Enum к int'у неявно не приводится.

Кстати, билд 164 так не думает.

S s = (S) e;

Здесь R#R не видит ошибки, если e -- значение перечислимого типа, а в S определен explicit operator (int). Компилятор против такого возражает (кроме случая S = IntPtr, который, он, почему-то считает допустимым).
Re[2]: Продолжаю непонимать C#. Теперь про операторы.
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 25.05.05 18:01
Оценка:
Здравствуйте, Mab, Вы писали:

X>>В IntPtr есть explicit operator IntPtr(int). В enum'е операторов нет. Enum к int'у неявно не приводится.

Mab>Кстати, билд 164 так не думает.

Дык я как раз переделываю правила преобразования типов в соответсвии с точной спецификацией языка. После переделки наткнулся на такое поведение IntPtr'а
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re: Продолжаю непонимать C#. Теперь про операторы.
От: Аноним  
Дата: 25.05.05 18:42
Оценка:
X>Вопрос: почему компилируется код

X>
X>enum E{A}

X>....
X>E e = E.A
X>IntPtr ptr = (IntPtr)e;
X>


X>Если совсем конкретно — то почему компилируется выделенный cast.


X>Поясню вопрос: в стандарте языка C# параграф 6.4.3 сказано, что при вызове explicit conversion оператора его параметр должен преобразовываться неявно.


X>В IntPtr есть explicit operator IntPtr(int). В enum'е операторов нет. Enum к int'у неявно не приводится.


Каждому члену enum соответствует значение int... если не задано явно то по порядку с 0... можно написать так
enum E{ A = 3 }
тогда элемент A будет соответствовать 3м
Re[2]: Продолжаю непонимать C#. Теперь про операторы.
От: Mab Россия http://shade.msu.ru/~mab
Дата: 25.05.05 20:38
Оценка:
А>Каждому члену enum соответствует значение int... если не задано явно то по порядку с 0... можно написать так
А>enum E{ A = 3 }
А>тогда элемент A будет соответствовать 3м
И какое это имеет отношение к обсуждаемому вопросу?
Re: Продолжаю непонимать C#. Теперь про операторы.
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 25.05.05 21:05
Оценка:
Здравствуйте, xvost, Вы писали:

Кстати, копаясь в интернете нашел что разработчики Mono наткнулись на те же грабли Правда что они сделали я еще не смотрел — не собраться с духом залезть в их код
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[2]: Продолжаю непонимать C#. Теперь про операторы.
От: Andir Россия
Дата: 26.05.05 01:46
Оценка:
Здравствуйте, xvost, Вы писали:

[skip]

X>Более того, если написать что-то типа

X>
X>struct S
X>{
X>  public static explicit operator S (int i) {....}
X>}
X>

X>То выражение
X>
X>S s = (S) e;
X>


В Моно это компилируется. (версия 1.0.5) Думаю это просто баг в MS C# Хотя в стандарте не сильно разбираюсь. Я так понимаю, что Enum должны неявно приводиться к нижележащему типу.
Мало того, в случае если отнаследовать Enum от беззнакового типа аля uint, ulong ... То компилироваться (опять же в mcs) перестают оба преобразования, что в IntPtr, что в тип с определённым явным преобразованием из int.
Так что в mono разночтений вроде и нет.

А вот в MS C# независимо от типа Enum преобразование в IntPtr работает. А с явно определённым оператором не работает. Видно явная поддержка со стороны компилятора у этого типа есть.

X>Кстати, копаясь в интернете нашел что разработчики Mono наткнулись на те же грабли Правда что они сделали я еще не смотрел — не собраться с духом залезть в их код


А зря, код по большей части очень приличный. Правда частенько разные части идут в разнобой с другими, но постепенно дорабатывается.

С Уважением, Andir!
using( RSDN@Home 1.1.4 beta 6a rev. 445 ) { /* Работаем */ }
Re: Продолжаю непонимать C#. Теперь про операторы.
От: Аноним  
Дата: 26.05.05 01:50
Оценка:
Уважаемый xvost!

Читайте, пожалуйста, спецификацию внимательно:

6.2.2 Explicit enumeration conversions

An explicit enumeration conversion between two types is processed by treating any participating enum-type as the underlying type of that enum-type, and then performing an implicit or explicit numeric conversion between the resulting types.

Данная информация предоставляется на условиях «КАК ЕСТЬ», без предоставления каких-либо гарантий и прав. Используя данную информацию, вы соглашаетесь с тем, что (i) Майкрософт не несет ответственности за использование вами данной информации и (ii) вы принимаете на себя весь риск, связанный с использованием данной информации.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[2]: Продолжаю непонимать C#. Теперь про операторы.
От: Аноним  
Дата: 26.05.05 01:57
Оценка:
В Моно это компилируется. (версия 1.0.5) Думаю это просто баг в MS C#

Нет, это баг в Mono. Xvost совершенно правильно описал (сославшись на стандарт), почему это не должно компилироваться. Только упустил из виду, что есть в стандарте другая статья — конкретно про перечислимые типы.

Я так понимаю, что Enum должны неявно приводиться к нижележащему типу.

Нет, enum должен приводиться к нижележащему типу явно. Опять же, читайте стандарт.

Видно явная поддержка со стороны компилятора у этого типа есть.

Нет там никакой поддержки. Это совершенно правильное поведение. Смотрите мой ответ автору с указанием ссылки на статью стандарта. Там это описано.
При таком преобразовании enum трактуется как нижележащий тип (в данном случае — int), а оператор преобразования int -> IntPtr существует.

Данная информация предоставляется на условиях «КАК ЕСТЬ», без предоставления каких-либо гарантий и прав. Используя данную информацию, вы соглашаетесь с тем, что (i) Майкрософт не несет ответственности за использование вами данной информации и (ii) вы принимаете на себя весь риск, связанный с использованием данной информации.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[3]: Продолжаю непонимать C#. Теперь про операторы.
От: Andir Россия
Дата: 26.05.05 02:10
Оценка:
Здравствуйте, Name, Вы писали:

N>[/i]Нет там никакой поддержки. Это совершенно правильное поведение. Смотрите мой ответ автору с указанием ссылки на статью стандарта. Там это описано.

N>При таком преобразовании enum трактуется как нижележащий тип (в данном случае — int), а оператор преобразования int -> IntPtr существует.

Тогда объясняйте до конца. Почему в MS C# не компилируется (а оператор преобразования int -> S есть!):
using System;

enum E { A }

struct S
{
  int _val;
  public S(int value){ _val = value; }
  public static explicit operator S (int value) { return new S(value); }
}

class MainClass
{
  static void Main()
  {
    IntPtr testPtr = (IntPtr)E.A;
    S s = (S) E.A; // error CS0030: Cannot convert type 'E' to 'S'
  }
}


C Уважением, Andir!
Re[3]: Продолжаю непонимать C#. Теперь про операторы.
От: Andir Россия
Дата: 26.05.05 02:20
Оценка:
Здравствуйте, Name, Вы писали:

A>>Видно явная поддержка со стороны компилятора у этого типа есть.


N>Нет там никакой поддержки. Это совершенно правильное поведение. Смотрите мой ответ автору с указанием ссылки на статью стандарта. Там это описано.

N>При таком преобразовании enum трактуется как нижележащий тип (в данном случае — int), а оператор преобразования int -> IntPtr существует.

И ещё вопросик. Если enum трактуется как нижележащий тип, то почему можно так (Ведь оператора явного ulong -> IntPtr не существует):
using System;

enum E : ulong { A }

class MainClass
{
  static void Main()
  {
    IntPtr testPtr = (IntPtr)E.A;
  }
}


C Уважением, Andir!
Re: Продолжаю непонимать C#. Теперь про операторы.
От: Andir Россия
Дата: 26.05.05 03:02
Оценка:
Здравствуйте, xvost, Вы писали:

X>Вопрос из серии "Помогите РеШарперу"


[skip]

Мало того enum можно вообще исключить и получить следующее:

using System;

struct S
{
    public S(int val){ _val = val; }
    public S(long val){ _val = (int)val; }
    
    int _val;
    
    public static explicit operator S (int val) { return new S(val); }
    public static explicit operator S (long val) { return new S(val); }
    // public static explicit operator S (ulong val) { return new S((long)val); }
}

class MainClass
{
    static void Main()
    {
        ulong val = 0;
            
        IntPtr p = (IntPtr)val;        
        S s = (S)val; // error CS0030: Cannot convert type 'ulong' to 'S'
    }
}


Если оператор явного преобразования из ulong не раскомментировать, то не компилируется, хотя в IntPtr такого оператора нет!

С Уважением, Andir!
using( RSDN@Home 1.1.4 beta 6a rev. 445 ) { /* Работаем */ }
Re[3]: Продолжаю непонимать C#. Теперь про операторы.
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 26.05.05 05:00
Оценка:
Здравствуйте, Andir, Вы писали:

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


X>>
X>>S s = (S) e;
X>>


A>В Моно это компилируется. (версия 1.0.5) Думаю это просто баг в MS C#


Если это так — то это баг в моно. Такое выражение _НЕ ДОЛЖНО_ компилироваться.

A>Хотя в стандарте не сильно разбираюсь. Я так понимаю, что Enum должны неявно приводиться к нижележащему типу.


Нет. Это неправда. параграф 6.1.3 гласит, что из неявных преобразований, в которых есть enum, разрешено только неявно приводить 0 к любому енуму.
enum к численному типу можно приводить только _явно_

A>Мало того, в случае если отнаследовать Enum от беззнакового типа аля uint, ulong ... То компилироваться (опять же в mcs) перестают оба преобразования, что в IntPtr, что в тип с определённым явным преобразованием из int.

A>Так что в mono разночтений вроде и нет.

Как видим, есть

A>А вот в MS C# независимо от типа Enum преобразование в IntPtr работает. А с явно определённым оператором не работает. Видно явная поддержка со стороны компилятора у этого типа есть.


Похоже не то, но мне пока не понять на каком уровне делать хак в системе приведения типов....
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[2]: Интересненько получается........ Не пойдет!
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 26.05.05 05:06
Оценка:
Здравствуйте, Name, Вы писали:

N>Уважаемый xvost!


N>Читайте, пожалуйста, спецификацию внимательно:


N> 6.2.2 Explicit enumeration conversions


N> An explicit enumeration conversion between two types is processed by treating any participating enum-type as the underlying type of that enum-type, and then performing an implicit or explicit numeric conversion between the resulting types.


Не пойдет!

Я копаю в сторону 6.4.4, который определяет правила поиска user-defined explicit conversion. Так вот там _ЯВНО_ сказано, что параметры могут приводиться только неявно (понятия encompassing type и encompassed type).

По-вашему, в этом случае все-равно enum можно трактовать как underlying тип......
Однако, почему тогда не компилируется такой код:


enum E : int {A}

struct T
{
  public static explicit operator T(int i)
  {
   return new T();
  }
}

.....
T t = (T) e


А он действительно не коспилируется, а по-вашему — должен?
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[2]: Продолжаю непонимать C#. Теперь про операторы.
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 26.05.05 05:10
Оценка:
Здравствуйте, Andir, Вы писали:

A>Если оператор явного преобразования из ulong не раскомментировать, то не компилируется, хотя в IntPtr такого оператора нет!


Тут все понятно и вопросов не возникает — ulong неявно не приводится ни к int, ни к long — вот компилятор и не может найти преобразования.
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[3]: Продолжаю непонимать C#. Теперь про операторы.
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 26.05.05 05:12
Оценка:
Здравствуйте, Name, Вы писали:

N>[/i]Нет там никакой поддержки. Это совершенно правильное поведение. Смотрите мой ответ автору с указанием ссылки на статью стандарта. Там это описано.

N>При таком преобразовании enum трактуется как нижележащий тип (в данном случае — int), а оператор преобразования int -> IntPtr существует.

Я Вам ниже написал, что это не так. Ибо построенный "руками" пример, в котором слово IntPtr заменено на другое — не компилируется. Мне видится что есть явная поддержка IntPtr'а, но не могу пока понять на каком уровне
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[3]: Продолжаю непонимать C#. Теперь про операторы.
От: Andir Россия
Дата: 26.05.05 05:14
Оценка:
Здравствуйте, xvost, Вы писали:

A>>Если оператор явного преобразования из ulong не раскомментировать, то не компилируется, хотя в IntPtr такого оператора нет!

X>Тут все понятно и вопросов не возникает — ulong неявно не приводится ни к int, ни к long — вот компилятор и не может найти преобразования.

Я на это и указал. Для IntPtr всё компилируется не смотря на такую же семантику.

C Уважением, Andir!
Re: Продолжаю непонимать C#. Теперь про операторы.
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 26.05.05 12:07
Оценка:
Здравствуйте, xvost, Вы писали:

Похоже на хак, который МСеры влепили в язык, дабы облегчить себе борьбу с интеропом.
... << RSDN@Home 1.1.4 beta 7 rev. 458>>
AVK Blog
Re[2]: Продолжаю непонимать C#. Теперь про операторы.
От: Козьма Прутков Россия  
Дата: 26.05.05 12:12
Оценка:
Аноним wrote:
> Каждому члену enum соответствует значение int... если не задано явно то по порядку с 0... можно написать так
> enum E{ A = 3 }
> тогда элемент A будет соответствовать 3м

The underlying type must be one of the built-in signed or unsigned
integer types (such as Byte, Int32, or UInt64).

Так что не всегда int.
Posted via RSDN NNTP Server 2.0 beta
Да хранит вас господь в сухом прохладном месте...
Re[2]: Продолжаю непонимать C#. Теперь про операторы.
От: andyJB  
Дата: 26.05.05 15:57
Оценка:
Здравствуйте, Name, Вы писали:

N> 6.2.2 Explicit enumeration conversions


N> An explicit enumeration conversion between two types is processed by treating any participating enum-type as the underlying type of that enum-type, and then performing an implicit or explicit numeric conversion between the resulting types.

Так как один из типов IntPtr, то explicit enumeration conversion здесь применяться не может. Оно преобразует enum в sbyte, byte и т.д. и обратно, а также enum'ы между собой. Здесь должно применяться 6.4.2 Evaluation of user-defined conversions.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.