Эта функция была в Spec # . Они по умолчанию обнулились ссылками и использовали! чтобы указать не обнуляемые. Это потому, что они хотели обратной совместимости.
На языке моей мечты (из которых я, вероятно, был бы единственным пользователем!) Я бы сделал такой же выбор, как и вы, по умолчанию не обнуляемый.
Я бы также сделал незаконным использование. оператор обнуляемой ссылки (или чего-либо еще, что могло бы разыменовать его). Как бы вы их использовали? Вы должны сначала преобразовать их в необнуляемые. Как бы вы это сделали? Проверяя их на ноль.
В Java и C # оператор if
может принимать только тестовое выражение bool
. Я бы расширил его, чтобы принять имя переменной ссылки, допускающей значение NULL:
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
не имеет значения NULL, но таковы два возможных результата теста выше, поэтому присваивание является значением.
А потом, возможно, немного сахара для предположительно распространенного случая замены значения на ноль:
string message = GetMessage() or "No message available";
Очевидно, что or
будет справедливо применяться только к обнуляемому типу на левой стороне и не обнуляемому на правой стороне.
(у меня также было бы встроенное понятие владения полями экземпляра; компилятор генерировал бы метод IDisposable.Dispose
автоматически, а синтаксис ~Destructor
использовался бы для увеличения Dispose
, точно так же, как в C ++ /CLI.)
Spec # имел другое синтаксическое расширение, связанное с ненулевыми значениями, из-за проблемы обеспечения правильной инициализации ненулевых элементов во время построения:
class SpecSharpExampleClass
{
private string! _nonNullableExampleField;
public SpecSharpExampleClass(string s)
: _nonNullableExampleField(s)
{
}
}
Другими словами, вы должны инициализировать поля таким же образом, как вы бы вызывали другие конструкторы с помощью base
или this
- если, конечно, вы не инициализируете их непосредственно рядом с объявлением поля.