null許容型を持つことは絶対的な悪だと一度読んだことがあります。それらを作った人(エイダで?)が書いた記事にあったと思いますこれが記事だと思います
とにかく、デフォルトでC#のような言語がnull許容型ではないタイプを使用した場合はどうなるでしょうか。C#、Ruby、またはnull
許容値である他の一般的な言語の一般的なイディオムのいくつかをどのように置き換えますか?
null許容型を持つことは絶対的な悪だと一度読んだことがあります。それらを作った人(エイダで?)が書いた記事にあったと思いますこれが記事だと思います
とにかく、デフォルトでC#のような言語がnull許容型ではないタイプを使用した場合はどうなるでしょうか。C#、Ruby、またはnull
許容値である他の一般的な言語の一般的なイディオムのいくつかをどのように置き換えますか?
null許容型が悪であると完全に宣言する代わりに、私は主張します。ほとんどの言語は、2つの概念が実際に直交する必要がある場合に、null許容性をすべての種類の型に移植します。
たとえば、すべての非プリミティブJava型(およびすべてのC#参照型)はnull許容です。なんで?行ったり来たりすることはできますが、最終的には「簡単だった」という答えになると思います。広範なヌル可能性を要求するJava言語に固有のものは何もありません。C ++リファレンスは、コンパイラレベルでnullを追い払う方法の良い例を提供しました。もちろん、C ++には、Javaが明示的に削減しようとしていたよりもはるかに醜い構文があるため、いくつかの優れた機能は、悪い機能と並んでカッティングフロアに行き着きました。
C#2.0のnull許容値型は、正しい方向へのステップを提供しました-無関係な型セマンティクス、またはさらに悪いことに、CLR実装の詳細からnull可能性を切り離します-しかし、参照型で反対を行う方法がまだありません。(コードコントラクトは素晴らしいものですが、ここで説明しているように型システムに組み込まれていません。)
多くの機能的またはその他のあいまいな言語は、最初からこれらの概念を「まっすぐ」にしています...しかし、それらが広く使用されていれば、この議論はありません...
あなたの質問に答えるために:現代語、卸売りからヌルを禁止することは、いわゆる「10億ドルの間違い」と同じくらい愚かです。nullが適している有効なプログラミング構造があります。オプションのパラメーター、合体演算子が簡潔なコードにつながるあらゆる種類のデフォルト/フォールバック計算、リレーショナルデータベースとの相互作用などです。センチネル値、NaNなどを使用するように強制します。病気よりもはるかに悪い「治癒」。
とは言うものの、私は自分の経験に合うように詳しく説明する限り、引用で表現された感情に暫定的に同意します。
null値を許可することが実際に望ましい(非常に)少数の場所でオプション型を使用します。オブジェクト参照が適切な型の有効なインスタンスを指すことが保証されるため、あいまいなバグがはるかに少なくなります。
Haskellは、nullityの概念を持たない強力な言語です。基本的に、すべての変数はnull以外の値に初期化する必要があります。「オプションの」変数を表したい場合(変数には値がある場合もありますが、ない場合もあります)、特別な「多分」タイプを使用できます。
Haskellではデータが不変であるため、C#よりもHaskellでこのシステムを実装する方が簡単です。したがって、後で入力するnull参照を持つことは実際には意味がありません。ただし、C#では、リンクリストの最後のリンクに次のリンクへのnullポインターが含まれている場合があります。このポインターは、リストが展開されるときに入力されます。null型のない手続き型言語がどのようになるかわかりません。
また、上記の多くの人がnullをタイプ固有の論理的な「nothing」値(999-999-9999、「NULL」など)に置き換えることを提案しているように見えることに注意してください。これらの値は実際には何も解決しません。なぜなら、nullに関して人々が抱える問題は、それらが特殊なケースであるということですが、人々は特殊なケースのコーディングを忘れているからです。タイプ固有の論理的なnothing値を使用すると、人々はまだ特殊なケースのコーディングを忘れますが、この間違いをキャッチするエラーを回避します。これは悪いことです。
あなたはこの話を参照していると思います:「ヌル参照:10億ドルの間違い」
単純なルールを採用できます。すべての変数は、変数のクラスによって定義された不変の値に初期化されます(デフォルトでは、これはオーバーライドできます)。スカラーの場合、これは通常、何らかの形のゼロになります。参照の場合、各クラスはその「null」値が何であるかを定義し、参照はこの値へのポインターで初期化されます。
これは事実上、NullObjectパターンの言語全体の実装になります。http://en.wikipedia.org/wiki/Null_Object_pattern したがって、実際にはnullオブジェクトを削除するのではなく、必要な特殊なケースにならないようにするだけです。そのように扱われます。
ヌルは問題ではありません。ヌルになる可能性のある値にアクセスするコードを記述できる言語です。
言語が最初にポインタアクセスをチェックするか、null許容型に変換する必要があるだけの場合、null関連のバグの99%が解消されます。例:C ++
void fun(foo *f)
{
f->x; // error: possibly null
if (f)
{
f->x; // ok
foo &r = *f; // ok, convert to non-nullable type
if (...) f = bar; // possibly null again
f->x; // error
r.x; // ok
}
}
残念ながら、これは多くのコードを壊してしまうため、ほとんどの言語に後付けすることはできませんが、新しい言語にはかなり合理的です。
Tclは、nullの概念を持たないだけでなく、nullの概念自体が言語のコアと対立している1つの言語です。tclでは、次のように述べています。「すべてが文字列です」。それが実際に意味するのは、tclには厳密な値のセマンティクスがあります(これはデフォルトで文字列になります)。
では、tclプログラマーは「データなし」を表すために何を使用するのでしょうか。ほとんどの場合、それは空の文字列です。空の文字列がデータを表すことができる場合、通常は次のいずれかです。
とにかく空の文字列を使用してください-ほとんどの場合、エンドユーザーには何の違いもありません。
データストリームに存在しないことがわかっている値を使用します。たとえば、文字列"_NULL_"
、数値9999999
、または私のお気に入りのNULバイト"\0"
などです。
値をラップしたデータ構造を使用します。最も単純なのはリスト(他の言語では配列と呼ばれるもの)です。1つの要素のリストは値が存在することを意味し、ゼロの要素はnullを意味します。
変数の存在をテストします- [info exists variable_name]
。
厳密な値のセマンティクスを持つ言語はTclだけではないことに注意してください。Cにも厳密な値のセマンティクスがありますが、値のデフォルトのセマンティクスは文字列ではなく整数です。
ああ、もう1つ忘れそうになりました。
一部のライブラリは、ユーザーが「データなし」のプレースホルダーを指定できるようにする番号2のバリエーションを使用します。基本的に、デフォルト値を指定できます(デフォルト値を指定しない場合、通常はデフォルトで空の文字列になります)。
他の回答に見られるように、オブジェクトが「無効である」または「存在しない」というメッセージを伝えるために、あらゆる種類の奇妙な構造を作成します。null
とてもよく伝わるメッセージ。
null
ラッパーの方が優れていますが、NullObjectパターンをチェックまたは使用することと大差ありません。個人的には、を使用できるC#プリプロセッサを作成しますnull
。次に、これはオブジェクトにマップされ、メソッドが呼び出されるたびdynamic
にをスローします。NullReferenceException
1965年に戻ると、null参照は間違いのように見えた可能性があります。しかし、今日では、null参照について警告するあらゆる種類のコード分析ツールがあれば、それほど心配する必要はありません。プログラミングの観点からnull
は、非常に価値のあるキーワードです。
現実的に言えば、そもそもポインタやオブジェクト参照を可能にする強力なプログラミング言語では、初期化コードが実行されていないポインタにコードがアクセスできる状況が発生します。そのようなポインタが静的な値に初期化されることを保証することは可能かもしれませんが、それはそれほど有用ではないようです。マシンに初期化されていない変数(ポインターなど)へのアクセスをトラップする一般的な手段がある場合、それは特殊なケースのnullポインターよりも優れていますが、そうでない場合、nullポインターを使用した算術を許可する実装で、null関連の最大の間違いが発生します。 。(char *)0に5を追加しても、アドレス5への文字ポインターは生成されません。エラーをトリガーする必要があります(絶対アドレスへのポインターを作成することが適切な場合は、
NULLなしで何をしますか?それを発明してください!:-)実際にはポインタではなく表現するインバンドポインタ値を探している場合は、0を使用するためにロケット科学者である必要はありません。
どちらかを使用します
弁別器。値が「null」であり、無視する必要があることを示す追加の属性またはフラグまたはインジケーター。
ドメイン固有のヌル。「この値を無視する」と解釈される特定の値(許可されたドメイン内)。たとえば、社会保障番号999-99-9999は、SSNが不明であるか、適用できないことを示すドメイン固有のnull値である可能性があります。