2009-03-28 5 views
12

Я разрабатываю язык, и мне интересно, можно ли по умолчанию использовать ссылочные типы, не имеющие значения null, и использовать «?». для значений с нулевым значением и ссылочными типами. Есть ли проблемы с этим? Что бы вы сделали по этому поводу:Ненужные ссылочные типы

class Foo { 
    Bar? b; 
    Bar b2; 
    Foo() { 
     b.DoSomething(); //valid, but will cause exception 
     b2.DoSomething(); //? 
    } 
} 
+0

Возможный дубликат [Лучшее объяснение для языков без пустых] (http://stackoverflow.com/questions/3989264/best-explanation-for-languages-without-null) – nawfal

ответ

16

Моя философия современного языка заключается в том, что нулеустойчивость должна быть чем-то, о чем программист вынужден просить, а не задаваться по умолчанию в ссылочных типах (в этом я согласен с Тони Хоаром - Google для его недавних разговоров QCon).

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

Мое отношение достаточно просто. Ссылки - это дескриптор косвенности для некоторого ресурса, который мы можем пройти, чтобы получить доступ к этому ресурсу. Нулекими ссылками являются либо дескриптор косвенности ресурса, , либо уведомление о том, что ресурс недоступен, и никто никогда не уверен в том, какая семантика используется. Это дает либо множество проверок спереди (это нулевое значение? Нет? Yay!), Либо неизбежный NPE (или эквивалент). Большинство ресурсов программирования, в эти дни, а не в широком масштабе с ограниченными ресурсами или связанные с некоторой конечной базовой модели - нулевые ссылки, упрощенно, один из ...

  • Лень: «Я просто затыкать нуль здесь» , Который, откровенно говоря, у меня нет слишком много сочувствия
  • Путаница: «Я еще не знаю, что добавить сюда». Как правило, это также наследие более старых языков, где вам нужно было объявить имена своих ресурсов, прежде чем вы узнаете, каковы ваши ресурсы.
  • Ошибки: «Пошло не так, вот NULL». Таким образом, более эффективные механизмы отчетности об ошибках необходимы на языке
  • Отверстие: «Я знаю, что у меня скоро что-то появится, дайте мне местозаполнитель». Это имеет большую ценность, и мы можем думать о способах борьбы с этим.

Разумеется, решение каждого случая, при котором NULL-ток удовлетворяет лучшим лингвистическим выбором, - это не маленький подвиг, и он может добавить больше путаницы, что он помогает. Мы всегда можем перейти к неизменяемым ресурсам, поэтому NULL в его только полезных состояниях (ошибка и дыра) мало используется. Императивные технологии здесь, чтобы остаться, и я искренне рад - это делает поиск лучших решений в этом пространстве стоящим.

3

Несколько примеров подобных функций в других языках:

Там также Nullable<T> (от C#), но это не очень хороший пример из-за различной обработки ссылочных и стоимостных типов.

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

b?->DoSomething(); 

Чтобы отправить сообщение b только если он не равен нулю.

4

Взгляните на предложение Elvis operator для Java 7.Это делает что-то подобное, поскольку оно инкапсулирует нулевую проверку и метод отправки в один оператор с указанным возвращаемым значением, если объект имеет значение null. Следовательно:

String s = mayBeNull?.toString() ?: "null"; 

проверяет, является ли строка s имеет нулевое значение, и возвращает строку «нуль», если это так, и значение строки, если нет. Возможно, пища для размышлений.

+3

Почему это называется оператором Элвиса? – Zifre

+0

Хороший вопрос, и один, на который я не знал ответа. Однако см. Http://www.infoq.com/articles/groovy-1.5-new re. оператор?:, который связан. Немного слабо, тем не менее ... –

+0

Я могу только предположить, что это какая-то шутка о том, что делать, если объект «покинул здание»? –

11

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

+0

Пожалуйста, изучите свое догматическое положение. – Kromster

-3

Я думаю, что нулевые значения хороши: они являются явным признаком того, что вы сделали что-то не так. Если вам не удалось инициализировать ссылку где-нибудь, вы получите немедленное уведомление.

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

+0

Иногда необходимо инициализировать что-то, не зная значения, которое оно в конечном итоге примет. Это относительно редко. Обычно инициализация происходит в той же строке, что и декларация. Кроме того, предложение не устраняет нулевые значения, а делает их не равными нулю по умолчанию. – kvb

+2

Кроме того, это неправда, что вы получите немедленное уведомление. Вы получите исключение, как только попытаетесь разыменовать нулевое значение, но это исключение можно поймать, и вы узнаете только во время выполнения, а не время компиляции. – kvb

+1

Проблема в том, что вы не можете заставить программистов инициализировать переменную correcty: сколько раз вы видели: DataSet ds = new DataSet(); ... ds = ReadDataSet (...); в коде? Если ds не имеют значения NULL, ошибка при обнаружении ошибки ReadDataSet() не будет обнаружена. – Lennaert

9

Эта функция была в Spec#. Они по умолчанию применяли нулевые ссылки и использовали! для указания непустых значений. Это было потому, что они хотели обратной совместимости.

На языке моей мечты (из которого я, вероятно, был бы единственным пользователем!) Я бы сделал тот же выбор, что и вы, по умолчанию не имеет значения по умолчанию.

Я также сделал бы незаконным использование. оператор по ссылке с нулевым значением (или что-нибудь еще, что бы разыменовать ее). Как бы вы их использовали? Сначала вам придется преобразовать их в не-nullables. Как бы вы это сделали? Проверяя их на null.

В Java и C# оператор if может принимать только тестовое выражение bool. Я бы продлить его принять имя обнуляемого ссылочной переменной:

if (myObj) 
{ 
    // in this scope, myObj is non-nullable, so can be used 
} 

Этот специальный синтаксис будет неудивителен для программистов C/C++. Я бы предпочел специальный синтаксис, подобный этому, чтобы было ясно, что мы делаем проверку, которая изменяет тип имени myObj в ветке правды.

Я хотел бы добавить еще немного сахара:

if (SomeMethodReturningANullable() into anotherObj) 
{ 
    // anotherObj is non-nullable, so can be used 
} 

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

Я бы сделал то же самое для оператора ?:.

string message = GetMessage() into m ? m : "No message available"; 

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

И тогда, возможно, немного сахара для предположительно общего случая подставляя значение нуля:

string message = GetMessage() or "No message available"; 

Очевидно or только будет правомерно применяться к обнуляемому типу с левой стороны, и не- с нулевым значением с правой стороны.

(я бы также иметь встроенное понятие собственности для полого экземпляра;. Компилятор генерирует метод IDisposable.Dispose автоматически, и синтаксис ~Destructor будет использоваться для увеличения Dispose, точно так, как в C++/CLI)

SpeC# был другой синтаксической расширение связано с не-nullables, в связи с проблемой обеспечения того, чтобы не-nullables были правильно инициализированы во время строительства:

class SpecSharpExampleClass 
{ 
    private string! _nonNullableExampleField; 

    public SpecSharpExampleClass(string s) 
     : _nonNullableExampleField(s) 
    { 

    } 
} 

другими словами, вы должны инициализировать поля в так же, как вы бы назвали другие конструкторы wit h base или this - если вы, конечно, не инициализируете их непосредственно рядом с объявлением поля.

+0

в вашем первом предложении, вы сказали, что «они по умолчанию ошибочно ссылаются на ссылки», вы имели в виду не-nullable? –

+1

@ Joan Venge - Нет. Позже в том же предложении я объясню, почему: SpeC# попытался скомпилировать существующий код C# правильно, поэтому ссылку следует считать нулевой, если только код не указывает иначе. –

+1

Спасибо, Дэниэл. Я думал, что SpeC# по умолчанию по умолчанию, потому что они думали, что это лучше, но я понимаю, что вы сейчас имеете в виду. –

-1

Уточните значение, которое должно быть параметром конфигурации, подлежащим исполнению в источнике авторов. Таким образом, вы позволяете людям, которым нравятся объекты с нулевым значением, по умолчанию пользуются ими в исходном коде, позволяя тем, кто хотел бы, чтобы все их объекты были не нулевыми по умолчанию, имеют именно это. Кроме того, укажите ключевые слова или другое средство для явного указания того, какие из ваших объявлений объектов и типов могут быть обнуляемыми и которые не могут, с чем-то вроде nullable и not-nullable, чтобы переопределить глобальные значения по умолчанию.

Например

/// "translation unit 1" 

#set nullable 
{ /// Scope of default override, making all declarations within the scope nullable implicitly 
    Bar bar; /// Can be null 
    non-null Foo foo; /// Overriden, cannot be null 
    nullable FooBar foobar; /// Overriden, can be null, even without the scope definition above 
} 

/// Same style for opposite 

/// ... 

/// Top-bottom, until reset by scoped-setting or simply reset to another value 
#set nullable; 

/// Nullable types implicitly 

#clear nullable; 

/// Can also use '#set nullable = false' or '#set not-nullable = true'. Ugly, but human mind is a very original, mhm, thing. 

Многие люди утверждают, что дает каждому то, что они хотят, это невозможно, но если вы разрабатываете новый язык, попробовать новые вещи. Тони Хоар представил концепцию null в 1965 году, потому что он не мог устоять (свои собственные слова), и мы платим за это с тех пор (также, его собственные слова, человек сожалеет об этом). Точка, умные, опытные люди делают ошибки, которые стоят для всех нас, не принимайте никаких советов на этой странице, как если бы это была единственная правда, включая мою. Оцените и подумайте об этом.

Я читал много много разговора о том, как это мы, бедные неопытные программисты, которые действительно не понимают, где действительно использовать null, а где нет, показывая нам образцы и антипаттерны, которые предназначены для предотвращения стрельбы в ногу. Все это время миллионы еще неопытных программистов производят больше кода на языках, которые позволяют null. I может быть неопытным, но я знаю, какие из моих объектов не могут быть обнуляемыми.

+0

Почему нисходящий? Вы видели, какие большие программы выглядят почти с каждой ссылкой, с префиксом чего-то вроде '@ NonNull'? Иногда меня шокирует состояние компьютерной науки, но потом еще что-то новое. Мы заслуживаем тех программ, которые у нас есть :-) – amn

Смежные вопросы