The null coalescing operator
От: ie Россия http://ziez.blogspot.com/
Дата: 20.09.06 08:53
Оценка:
Помогите разобраться. Есть такой код:

    int? i1 = 1;
    int? i2 = 2;
    int? inull = null;

    Console.WriteLine("(i1 ?? i2) : " + (i1 ?? i2).GetType()); // System.Int32
    Console.WriteLine("(i1 ?? inull) : " + (i1 ?? inull).GetType()); // System.Int32
    Console.WriteLine("(inull ?? i2) : " + (inull ?? i2).GetType()); // System.Int32
    Console.WriteLine("(inull ?? inull) : " + (inull ?? inull).GetType()); // Exception: System.NullReferenceException


По спецификации:

The type of the expression a ?? b depends on which implicit conversions are available between the types
of the operands. In order of preference, the type of a ?? b is A0, A, or B, where A is the type of a, B is the
type of b, and A0 is the type that results from removing the trailing ? modifier, if any, from A. Specifically,
a ?? b is processed as follows:
• If A is not a nullable type or a reference type, a compile-time error occurs.
• If A is a nullable type and an implicit conversion exists from b to A0, the result type is A0. At run-time, a
is first evaluated. If a is not null, a is unwrapped to type A0, and this becomes the result. Otherwise, b is
evaluated and converted to type A0, and this becomes the result.

• Otherwise, if an implicit conversion exists from b to A, the result type is A. At run-time, a is first
evaluated. If a is not null, a becomes the result. Otherwise, b is evaluated and converted to type A, and
this becomes the result.
• Otherwise, if an implicit conversion exists from A0 to B, the result type is B. At run-time, a is first
evaluated. If a is not null, a is unwrapped to type A0 (unless A and A0 are the same type) and converted
to type B, and this becomes the result. Otherwise, b is evaluated and becomes the result.


Итак, судя по выделенному:
(i1 ?? i2) -> A == int?, B == int?, A0 == int
Из B (как впрочем и из i2) у нас нет implicit conversion в A0
Судя по следующему, за выделенным пунктом, тип результата должен быть A. Но это не так. Почему?

Аналогичные проблемы и для остальных случаев. Особенно меня беспокоит случай №4, что мешало остаться нуллаблом?
Я что-то упустил или неправильно понимаю?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Превратим окружающую нас среду в воскресенье.
Re: The null coalescing operator
От: Lloyd Россия  
Дата: 20.09.06 08:58
Оценка:
Здравствуйте, ie, Вы писали:

ie>Аналогичные проблемы и для остальных случаев. Особенно меня беспокоит случай №4, что мешало остаться нуллаблом?

ie>Я что-то упустил или неправильно понимаю?

Неправильно понимаешь. GetType — это не оператор получения типа выражения, это метод, возвращающий тип объекта, у которого этот метод был вызван. Если объект == null, то обращение к его методам бросает NullReferenceException.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: The null coalescing operator
От: _FRED_ Черногория
Дата: 20.09.06 09:11
Оценка: 12 (1)
Здравствуйте, Lloyd, Вы писали:

L>Если объект == null, то обращение к его методам бросает NullReferenceException.


namespace ConsoleApplication1
{
  using System;

  class Program
  {
    static void Main() {
      int? value = null;
      if(value == null) {
        Console.WriteLine("value.HasValue = {0}", value.HasValue);
      } else {
        Console.WriteLine("value == null");
      }//if
    }
  }
}
... << RSDN@Home 1.2.0 alpha rev. 652>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re: The null coalescing operator
От: _FRED_ Черногория
Дата: 20.09.06 09:19
Оценка: 19 (2)
Здравствуйте, ie, Вы писали:

ie>Помогите разобраться …


Где-то ты наврал:
namespace ConsoleApplication1
{
  using System;

  class Program
  {
    static void Main() {
      int? i1 = 1;
      int? i2 = 2;
      int? inull = null;

      Console.WriteLine("(i1 ?? i2) : " + GetArgumentType(i1 ?? i2)); // System.Nullable`1[System.Int32]
      Console.WriteLine("(i1 ?? inull) : " + GetArgumentType(i1 ?? inull)); // System.Nullable`1[System.Int32]
      Console.WriteLine("(inull ?? i2) : " + GetArgumentType(inull ?? i2)); // System.Nullable`1[System.Int32]
      Console.WriteLine("(inull ?? inull) : " + GetArgumentType(inull ?? inull)); // System.Nullable`1[System.Int32]
    }

    static Type GetArgumentType<T>(T argument) {
      return typeof(T);
    }
  }
}
... << RSDN@Home 1.2.0 alpha rev. 652>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re[2]: The null coalescing operator
От: ie Россия http://ziez.blogspot.com/
Дата: 20.09.06 09:24
Оценка:
Здравствуйте, Lloyd, Вы писали:

ie>>Аналогичные проблемы и для остальных случаев. Особенно меня беспокоит случай №4, что мешало остаться нуллаблом?

ie>>Я что-то упустил или неправильно понимаю?

L>Неправильно понимаешь. GetType — это не оператор получения типа выражения, это метод, возвращающий тип объекта, у которого этот метод был вызван. Если объект == null, то обращение к его методам бросает NullReferenceException.



Угу не правильно, думал, что
    int? i1 = 1;
    Console.WriteLine(i1.GetType());
    Console.WriteLine(typeof(int?));

выведут одно и тоже.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Превратим окружающую нас среду в воскресенье.
Re: The null coalescing operator
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 20.09.06 09:38
Оценка: 37 (3)
Здравствуйте, ie, Вы писали:

ie>Помогите разобраться. Есть такой код:


Все прозрачно как ясный денью Смотри:

1) nullable тип не умеет бокситься. При попытке его забоксить будет забокшено underlying value
2) GetType требует объекта в хипе, а не на стэке. Ибо объект на стэке не имеет GCHandle'а, и, как следствие, не обладает метаинформацией

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

1)

int i = 0;
i.GetType();


посмотри на IL — там будет боксинг

2) в твоем примере напиши не GetType(), а, например, GetHashCode — все перестанет падать
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[2]: The null coalescing operator
От: ie Россия http://ziez.blogspot.com/
Дата: 20.09.06 09:53
Оценка:
Здравствуйте, xvost, Вы писали:

ie>>Помогите разобраться. Есть такой код:

X>Все прозрачно как ясный денью Смотри:

Это понравилось!

X>1) nullable тип не умеет бокситься. При попытке его забоксить будет забокшено underlying value

X>2) GetType требует объекта в хипе, а не на стэке. Ибо объект на стэке не имеет GCHandle'а, и, как следствие, не обладает метаинформацией

Да, то что GetType не виртуальный, а следовательно не может быть вызван для value типов без боксинга, не учел.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Превратим окружающую нас среду в воскресенье.
Re[3]: The null coalescing operator
От: nikov США http://www.linkedin.com/in/nikov
Дата: 21.09.06 05:53
Оценка:
Здравствуйте, ie, Вы писали:

ie>Да, то что GetType не виртуальный, а следовательно не может быть вызван для value типов без боксинга, не учел.


Например, следующий код вобще не скомпилируется:

new TypedReference().GetType();
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.