Тип значения C#, инициализированный нулем

В С# 3.0 вы можете присвоить значение null для int? тип (в CLR int? является структурой):

int? a = null;

но когда вы определяете пользовательскую структуру:

struct MyStruct
{

}

при компиляции этого кода возникает ошибка:

MyStruct a = null;

Ошибка заключается в следующем:

Cannot convert null to 'Example.MyStruct' because it is a non-nullable value type

В то время как инт? является структурой в CLR, как-то нелогично, что мы можем присвоить ей значение null. Я полагаю, что null неявно приводится или помещается в certian int? значение, представляющее нулевое значение. Как именно это делается? Как я могу расширить MyStruct таким образом, чтобы можно было выполнить строку:

MyStruct a = null;

person mgamer    schedule 24.11.2010    source источник


Ответы (3)


Это потому, что int? на самом деле является сокращением Nullable<int>. Вы можете сделать то же самое и для своего типа:

MyStruct? a = null;

null можно только неявно преобразовать в тип nullable, что означает любой ссылочный тип или любой тип значения, допускающий значение null, где последний означает Nullable<T> для некоторого T.

Обратите внимание, что эта возможность преобразования из null на самом деле является особенностью языка — компилятор преобразует это:

int? a = null;

в

int? a = new int?();

Они означают одно и то же — в основном «нулевое» значение для типа значения, допускающего значение NULL, — это значение, где HasValue равно false, что и будет по умолчанию. Это не то же самое, что пустая ссылка, хотя такое помещение нулевого значения будет приводить к нулевой ссылке.

(Это один из примеров функции, которая пересекает границы языка, библиотеки и среды CLR. Библиотечная часть довольно проста, часть CLR предназначена только для упаковки и распаковки, но в языке довольно много операций поднятия и т. д. .)

person Jon Skeet    schedule 24.11.2010
comment
Интересное время для этого вопроса. Я только что закончил читать главу о типах, допускающих значение NULL, в книге Джона (C# in Depth). Его должен прочитать каждый разработчик C#!! Спасибо, Джон. - person Bryan; 24.11.2010
comment
Я просто хотел отметить, что я не платил за этот комментарий :) - person Jon Skeet; 24.11.2010
comment
Ваше утверждение Обратите внимание, что это действительно языковая функция, которая несколько сбивает с толку, поскольку CLR делает (как вы упоминаете позже) обрабатывает структуры Nullable<> специально в операциях упаковки и распаковки, что, ИМХО, делает эту функцию времени выполнения (с немного ? синтаксического сахара в довершение всего). - person Lucero; 24.11.2010
comment
@Lucero: преобразование из нулевого литерала - это языковая функция. Я отредактирую, чтобы было понятнее. - person Jon Skeet; 24.11.2010
comment
@Jon Skeet: Итак, моя проблема связана с языковой функцией, о которой вы упомянули. Можно ли каким-то образом использовать эту языковую функцию для автоматического преобразования MyStruct a = null в MyStruct a = new MyStruct() ? - person mgamer; 24.11.2010
comment
@mgamer: Нет; это применимо только к Nullable<T>. - person Jon Skeet; 24.11.2010
comment
@ Джон, я понимаю, что ты имеешь в виду. Однако еще один комментарий-вопрос: почему вы решили написать new int?() вместо default(int?) (что верно для всех типов, допускающих значение NULL, будь то ссылка или Nullable<>)? (Редактировать: это также относится к комментарию mgamer.) - person Lucero; 24.11.2010

Структуры — это типы значений в C#, а не ссылочные типы, поэтому они не могут быть нулевыми.

MyStruct? = null;

будет работать, но помните, что структуры неизменяемы, например:

public struct Point 
{
   public int x, y;

   public Point(int p1, int p2) 
   {
       x = p1;
       y = p2;    
   }
}

void Main()
{

    //create a point
    var point1 = new Point(10, 10); 

    //assign point2 to point, point2
    var point2 = point1; 

    //change the value of point2.x
    point2.x = 20; 

    //you will notice that point1.x does not change
    //this is because point2 is set by value, not reference.
    Console.WriteLine(point1.x);
    Console.WriteLine(point2.x);

}
person Master Morality    schedule 24.11.2010
comment
Что ж, MyStruct? по-прежнему является типом значения, но он может быть нулевым. - person Jon Skeet; 24.11.2010
comment
И не все структуры неизменяемы (к сожалению). - person Jon Skeet; 24.11.2010
comment
@Jon: я думал, что структуры передаются по значению, как они могут не быть неизменными? - person Master Morality; 27.11.2010
comment
@Master: То, что они передаются по значению, не делает их неизменяемыми. См., например, System.Drawing.Point — вы можете создать экземпляр, а затем установить его свойства X и Y. - person Jon Skeet; 28.11.2010
comment
@Jon: Я всегда думал, что point1.x = 1; соответствует point1 = new Point(1, point1.y);. Хотя, наверное, я так справляюсь... - person Master Morality; 29.11.2010
comment
@Master: Нет, это не так - в частности, не должно быть быть такого конструктора, или если бы такой конструктор был, код внутри него не был бы бегать. - person Jon Skeet; 29.11.2010

просто добавляя, тип, допускающий значение NULL, может представлять нормальный диапазон значений для своего базового типа значения, а также дополнительное значение NULL.

В нотации, поскольку int на самом деле является Int32, а не любым int, ? знак означает значение nullable. Nullable, в этом случае.

http://msdn.microsoft.com/en-us/library/1t3y8s4s%28VS.80%29.aspx

person marcelo-ferraz    schedule 24.11.2010