Приведение к нулю не компилируется - PullRequest
8 голосов
/ 25 января 2012

случайно на работе написал следующую строчку кода:

string x = (object) null; 
// It was var x = (object)null and I changed from var to string instead of 
// object x = null;

Это дало мне ошибку компиляции, подобную этой: Can't cast source type object to target type string

Почему? Разве null не является просто набором нулей, указывающих на «никуда» адрес памяти, независимо от типа?

Ответы [ 7 ]

23 голосов
/ 25 января 2012

Проблема не в приведении null, а в том, что object нельзя присвоить string.Это прекрасно работает

string x = (string)null;

Причина, по которой это работает, если вы удалите приведение (string x = null), изложена в разделе 2.4.4.6 спецификации языка C #

Нуль-literal может быть неявно преобразован в ссылочный тип или обнуляемый тип

В тот момент, когда вы вводите приведение ((object)null), у вас больше нет нулевого литерала.Вместо этого у вас есть значение типа object.По сути, ничем не отличается от

object temp = null;
string x = temp;
11 голосов
/ 25 января 2012

Вопрос здесь в основном «почему компилятор не принимает во внимание тот факт, что он знает, что присвоенное значение является константной ссылкой, известной как нулевая?»

Ответ: зачем это?В чем убедительная выгода от принятия этой информации во внимание?Вы сознательно сказали: «Я хочу, чтобы это выражение обрабатывалось так, как если бы оно было объекта типа», и вы не можете присвоить значение объекта типа переменной типа string.Какая польза от этого в этом случае?

Мне кажется, что код, скорее всего, будет ошибкой;несомненно, компилятор должен сообщать вам об этом, а не разрешать это.

5 голосов
/ 25 января 2012

Не является ли ноль просто набором нулей, указывающих на «никуда» адрес памяти, независимо от типа?

Это все, что есть на языке со слабой типизацией, таком как C или C ++.

В C # тип ссылки является неотъемлемой частью ее идентичности. (string)null - это не то же самое, что (object)null, потому что один - string, а другой - object.

Кроме того, в C # null на самом деле не имеет числового эквивалента. Ссылки в C # - это не то же самое, что указатели, и, говоря семантически, они не имеют ассоциированного адреса памяти. null просто означает, что ссылка не указывает на объект, а внутреннее представление ссылки null является подробностью реализации.

3 голосов
/ 25 января 2012

Он должен быть назначаемым - даже если может показаться, что он «тот же нуль» и это не должно иметь значения, компилятор все еще поддерживает тип.Одним из преимуществ этого является разрешение перегрузок:

void Foo(object bar) { ... }
void Foo(string bar) { ... }

Foo((object)null); // will call the former
Foo((string)null); // will call the latter
2 голосов
/ 25 января 2012

возможно object x = (string) null; это может сработать, но с чего бы вам?

потому что объект может содержать строку, но строка не может содержать объект

строка наследуется от объекта, а не наоборот.

0 голосов
/ 25 января 2012

У каждого класса есть список определений для:

Constructors
Destructors
Fields
Methods
Properties
Indexers
Delegates
Events
Nested Classes

Объект является универсальным типом, потому что каждый класс наследуется от него, но не наоборот.Эти определения не одинаковы для каждого класса, поэтому ваш компилятор может решить, какие типы вы можете назначить / привести друг к другу.

Затем вы делаете: string x = (object)null;

Компилятору все равноэто значение, которое вы пытаетесь присвоить своему x в первую очередь, но оно проверяет определения типов строки и просто не позволяет вам стрелять в собственную ногу и генерирует ошибку, потому что это несоответствие типов.

0 голосов
/ 25 января 2012

Вы можете присвоить значение null любой переменной ссылочного типа, ничего не приводя:

String x = null;
...