Dを選択する理由

導入する代わりに



こんにちは、ハブラルディ。

プロジェクトのプログラミング言語を選択するささやかな経験すべてと共有したいと思います。 すぐに強調したい-私は自分のニーズに基づいて言語を選択しましたが、同様の条件での選択は異なる可能性があります。 それにもかかわらず、DをC ++およびC#と非常に徹底的かつ合理的に比較し、異なるクラスに属し、異なるパラダイムを実装する10を超える言語と同様に、この記事が役立つことを心から願っています。 D自体は、システムおよびアプリケーションプログラミング用の高レベル言語として開発されています。



また、DにはD1とD2の2つのバージョンがあることに注意してください。 D1は安定しており、その更新はバグ修正のみに影響し、D2は現在新しい機能を追加しています。 D2は新しいプロジェクトに推奨されているため、特に断りのない限り、記事で検討されるのは彼です。



一般的なプログラミング言語の範囲について



それでは始めましょう。 まず、プログラミング言語の選択は主にタスクの範囲に依存することに注意してください-C / C ++ / Java / C#は、WebページのJavaScriptまたはリレーショナルデータベースのSQLを置き換えることはできません。 ここでは、おそらく予約が必要ですが、原則として、コンパイラを作成するか、特定のルールに従って1つの言語を別の言語に変換するクラスのライブラリを作成できます。 そのため、たとえば、MicrosoftはASP.NETプラットフォームの開発時に-ブラウザスクリプトを.NETプラットフォームの任意の言語(C#など)で記述し、対応するJavaScriptコードに自動的に変換できます。 ただし、ブラウザのフォームバリデータを生成する比較的単純な例についてのみこの機能を個人的にテストしたため、非標準の場合はJavaScriptを使用する必要がある可能性があります。 一方、最新のすべてのブラウザでテストされたフリーウェアライブラリとフレームワーク(jQuery、MooTools、Prototypeなど)の数を考えると、車輪を再発明する価値はないかもしれません。 また、たとえば、さまざまなテクノロジーへの言語の適用性について話しているため、オペレーティングシステムを記述するために関数型プログラミング言語(Haskellなど)を選択できますが、システムプログラミング言語としてJavaScriptを選択するのはおそらく無理でしょう。 ところで、Haskellの1つのOSはすでに記述されています。Houseと呼ばれます。 チューリングの完全性がないため、SQLでアプリケーションプログラムを作成することはできません。 Transact-SQLはすでにそのような完全性を備えていますが、Microsoft SQL ServerとSybase ASEでのみサポートされているため、この言語はアプリケーションプログラムの作成には適していません。



2番目は、もちろん、プロジェクトマネージャーの選択です。 C ++が非常に人気があるのは、約5年前に人気があったからです。 言い換えると、プログラミング言語を選択する場合、プロジェクトマネージャーは、あまり知られていない言語(たとえば、HaskellやCommon Lisp)よりもよく知られている言語(同じJavaとC ++)を優先します。後者は、この特定のプロジェクトにより適しています。 問題は、なぜですか? 哲学は非常に単純です。マネージャーがC ++プロジェクトをあふれさせる場合、彼は毎年何百ものプロジェクトがC ++で死ぬという事実を正当化しようとすることができます。 Haskellでは、このケースではマネージャー自身が比較的めったに使用されないテクノロジーの使用を主張したため、うまくいきません。 私の観点からは、これは言い訳ではありません。なぜなら、マネージャーはこの問題領域に最も適したプログラミング言語を提供し、言語の人気のために考えられる言い訳に導かれるべきではないからです。 もちろん、これは放棄された役に立たない言語でプログラムする必要があるという意味ではありません。 私はあなたが言語を選ぶ際に創造的である必要があることを強調したいだけです。 たとえば、一部の関数型言語(Common Lisp、Scheme、Haskellなど)は、コンピューター代数の問題の解決に適している場合があります。そのような言語の数式は、命令型言語よりも馴染みのある「数学」形式に見えるからです。 以下は、漸化式として階乗を計算するサンプルHaskellコードです。

階乗::整数->整数
 階乗0 = 1
 階乗n |  n> 0 = n *階乗(n-1)


それは教科書の式に非常に似ていませんか? 実際、Maximaの無料のコンピュータ代数システムはCommon Lispで書かれており、その能力はMapleとMathematicaに匹敵します。

これをすべて言ったが、私は言語の選択が本当に重要であることを強調したいだけです。 すべての言語が平等であるわけではありませんが、それらの中でより平等です。 信じられない? Brainfuckで「Hello World!」を印刷するプログラムの例を次に示します。

 ++++++++++ [> +++++++> +++++++++++ +++> + <<<<-]> ++
  。> +。+++++++ .. +++。> ++。<< +++++++++++++++。>。+++。
  ------.--------。> +。>。


すぐに明確にしたい-8つのコマンドのみを含むこの難解な言語は、楽しみのためにUrbanMüllerによって作成されましたが、それでもチューリング完全であるため、SQLではできないことを書くことができます。 唯一の質問は、より多くの価値のある候補者がいるときに誰がそれを必要とするかです。 おそらく、ミューラーが強調したかったのはまさにこの考えであり、有名な英語の呪いに合わせて言語に名前を付けました。 別の考えられる説明は、その人気を何らかの形で高めるために、言語に覚えやすい名前を付けることです。



最後に、自分の好みが言語の選択に影響する場合があります。 さて、突然の最初の2つの制限がすべて十分でない場合。



さらに、主に応用プログラミング用の言語の選択に焦点を当てます。 それでは、なぜDはそんなに魅力的ですか? 実際、誰もがこの質問に自分で答えるべきですが、私は彼の選択によって導かれた要因を説明しようとしています。 同時に、必要な言語の種類を理解するには、既存の言語の欠点を把握し、可能な候補のリストを決定する必要があります。



C#の欠陥について少し



順番に始めましょう。 アプリケーションプログラミングの言語としてC#を選択してみませんか? 私にとって非常に重要な主な問題は、中間言語であるCommon Intermediate Language(CIL)へのコンパイルです。これにより、逆コンパイルが簡単なタスクになります。 さらに、このための特別なツールがあります。 たとえば、.NET Reflectorは、変数、関数、およびクラスの元の名前を保存するなど、エラーなしでC#/ VB.NET / F#ソースコードを生成します。 結果のソースコードは、コメントがないことを除き、元のソースコードとは異なります。 実験をしたい人は、 公式サイトからプログラムの試用版をダウンロードできます。



したがって、同じC ++でコンパイルされたプログラムを分析するのに、逆アセンブラーで作業する能力など、十分な知識が必要な場合は、C#でソースコードを取得するのに数分かかります。 もちろん、これはすべてオープンソースの支持者には関係ありませんが、ここでも反対することができます。プログラムを無料にしたい場合は、ソースコードを公開します。そうでなければ、プログラムを閉じたままにする理由があります。 最終的に、すべてのソフトウェアが無料というわけではありません。 さまざまな追加命令でプログラムのソースコードを認識できないほど変更したり、内部インターフェイスと変数名を変更したり、例外的な状況を追加したり、コードの暗号化などを行うことができるサードパーティの難読化プログラムがあることに注意してください これにより、C#でプログラムを分析することは非常に困難になります。 難読化ツールの重大な欠点は、オリジナルよりも遅いコードの生成、プログラムにエラーを導入する可能性、難読化ツール自体をハッキングする可能性です(その後、その保護は誰にとっても役に立たなくなります)。 ちょっと考えてみてください。何年もの間、人々はコンパイラを改善し、開発ツールをより良く作成し、最適化しようとしていますが、ここで何らかのリグレッションが起こります。



ただし、バイナリコードにコンパイルすることの重要性の問題は、アプリケーションの領域に依存します。プログラムが開発会社の外部で使用される予定がない場合、ほとんどの場合、プログラミング言語を選択するときに逆コンパイルの危険性は決定的な要因にはなりません。 線を引くために、MicrosoftのC#コンパイラの標準パッケージにプログラムをバイナリコードにコンパイルするツールがありますが、プログラムはCILのソースコードなしでは機能しません。 したがって、ハッキングから保護するために使用することはできません。



C#を使用する前に2番目に考えることは、結果のコードの移植性です。 Oktalの言葉を引用させてください。「Microsoftが.Netテクノロジーに名前を付けたので、Unixのディレクトリリストに表示されません。」 著者が正しいかどうかはわかりませんが、C#からWinAPI関数、COMオブジェクト、およびプログラムを耐えられないものにする他のコンポーネントを呼び出すのは非常に簡単です。 Windows固有のコンポーネントを使用しなくても、プログラム自体はUnixシステムでは実行されません—実行にはMonoが必要です。 はい、もちろん、Monoはよく知られた製品ですが、使用すると問題が発生する可能性があります。 最初に心に留めておくべきことは、Mono開発者は常にリリース済みのライブラリと標準の実装を開始するため、Microsoftの一歩先を行くということです。 第二:そして、彼らは誤って退屈しないのですか? はい、これはコミュニティを開発している無料ライセンスプロジェクトであることを理解していますが、サポートを終了するリスクがまだあります。 これは既存のアプリケーションには影響しませんが、新しいライブラリのサポートがないため、新しいプログラムは耐えられなくなる可能性があります。 3番目に覚えておくべきことは、MicrosoftのWinForms、ADO.NET、およびASP.NETコンポーネントの標準がないことです。 これらの使用にはMicrosoftからの法的請求が伴う場合があるため、Monoと一緒に使用することは推奨されません。 後者は、さまざまなサイズのサイトを構築するために使用される優れたASP.NETコンポーネントには、同じPHPよりもまったく利点がないことを意味します。 突然、プロジェクトで使用したい場合は、サーバーバージョンのWindowsのライセンスを購入する心構えを整えてください。



最後に、自問する3番目のこと:マイクロソフトはこの言語の開発を続けますか? 現在、すべてのC#/ CLI特許はMicrosoftが所有しており、それをサポートできなかった場合、この言語は消滅します。 個人的には、C#は進化し続けると信じています-マイクロソフトはこの言語に投資しすぎています。 しかし、誰も保証することはできません。Microsoftは、かつてVisual Basicのサポートを拒否し、代わりに完全に新しい言語であるVisual Basic .NETを作成しました。 その結果、これにより、Basicに取り組んでいる何千人ものプログラマーが悲劇に陥りました。 さらに、報道によると、2015年から2016年にかけて、マイクロソフトはタブレット、スマートフォン、コンピューター、コンソール、テレビ、その他のデバイス用の新しいOSを作成することでWindowsブランドを放棄する予定です。忘却に沈むこともできます。



個人的には、これらの議論はC#の使用を拒否するのに十分です。 誤解しないでください:C#は素晴らしい現代言語ですが、主にWindowsにのみ適していますが、それでもすべての場合に当てはまりません。 少し考えてみると、.NETプラットフォームの使用はC#と同じくらい危険であると結論付けることができます。 したがって、私の個人的な意見では、このプラットフォームに主に焦点を当てた言語で書くべきではないということです。 たとえば、NemerleはC#よりも優れた優れた言語であり、その主な機能は開発されたメタプログラミングシステムであり、関数型プログラミングとオブジェクト指向プログラミングの機能を組み合わせています。 しかし、言語設計は主に.NETプラットフォームに焦点を当てており、多くのプロジェクトでの使用の可能性に疑問を投げかけています。 F#は、.NETプラットフォーム用の関数型プログラミング言語の優れた例であり、Haskellに多少似ており、数学指向システムの開発に適している場合があります。 しかし、再び、.NETプラットフォームはその使用を制限します。



C#と.NETプラットフォームを愛する人たち! これらの技術には多くの利点があることをよく知っています。まず第一に、これは(ほとんど)何でもできる巨大なクラスライブラリです。 残念ながら、.NETプラットフォームの利点を詳細に確認するには、ほぼ同じボリュームの記事を書く必要があるため、このテクノロジとその機能が意図的に不完全に網羅されていることをおaびします。



C ++の欠陥について少し



なぜC ++を選択しないのですか? もちろん、これは誰もが聞いたことがある業界標準です。 しかし実際には、この言語にはいくつかの重大な欠点があり、そのうちのいくつかを検討してみます。 最初に頭に浮かぶのは、この言語は複雑だということです。 より正確には、非常に複雑です。 それに比べて、C#での作業は幼稚な楽しみのように思えます。 自分で判断してください:Cの標準だけで約500ページ、C ++-約800、C ++ 11-約1300かかります。技術文書の量を比較すると、この言語は明らかに飛行機、飛行機、ミシン、車よりも難しいです。 比較のために、C#4.0標準は505ページのみを取ります。 この時点で、アラン・カーティス・ケイからの引用を思い出したいと思います。「「オブジェクト指向」の概念を発明しましたが、同時にC ++を意味していなかったと言えます。」 対照的に、もちろん、C ++の作成者であるBjarne Stroustrupを思い出すことができます。「誰もが文句を言う言語と、誰も使用していない言語は2種類しかありません」が、この引用は言い訳のように聞こえます。 この意味でDは非常に便利な言語です-その設計は主にC#とJavaに基づいて設計されました。 D1仕様の範囲は223ページです。 D2の仕様は、コンパイラを備えたhtmlページの形式で提供されます。これは、公式Webサイトwww.d-programming-language.orgでも入手できます。 さらに、Andrei Alexandrescu(The D Programming Language)による本があります。これは、実際にはD2標準の説明です(ボリューム-492ページ、現在ロシア語に翻訳されています)。 したがって、言語自体の複雑さは、プログラミングを容易にしません。 Dでは、すべてがよりシンプルでスマートになり、理解しやすくなりました。



安全第一



C ++の次の主要な欠点は、エラーのコンパイル中のコードチェックが不十分なことです。 言い換えると、C ++では、コンパイルされるが正しく動作しないコードを書くのは非常に簡単です。 言語のこのような論争の的となっている機能の完全なリストの編集は専門家に任せ、配列要素演算子[]の取得演算子(インデックス付け操作)に限定します。 この言語が配列要素の境界をチェックしないという事実は、誰にも秘密ではないと思います。 ただし、これにも関わらず、バッファオーバーフローエラーはCおよびC ++プログラムで発生していました。 プログラマーはこれらの間違いを犯しますが、その理由は、まさにその外観に寄与する言語にあると考えています。 たとえば、C#は常に配列の制限を超えてチェックを行うため、このようなエラーは非常に少なくなりますが、パフォーマンスが低下します(コンパイラーまたは標準ライブラリーの実装で発生する可能性のあるエラーにより、バッファーオーバーフローが依然として発生する可能性があります)。 STLライブラリは多くの問題を解決しますが、これは正しく使用された場合にのみ当てはまります。 たとえば、ベクトルテンプレートクラスは、インデックス操作(演算子[])の使用時に境界を超えているかどうかをチェックしません。境界をチェックするには、at関数を使用する必要があります(H. M. Daytel、P.J。Daytel、「How to program in C ++」)。 つまり、STLは万能薬ではありません。



実際、バッファオーバーフローエラーは、一見思われるよりも深刻な問題です。 1988年にインターネットを麻痺させた有名なMorris Wormは、この特定のタイプのエラーを使用しました(損害は9,600万ドルと推定されます)。 別の例:Return指向のプログラミング手法を使用する場合、システムのその後のハッキングのために2〜3個のアセンブラー命令のみを実装すれば十分です。 つまり、1バイトのバッファオーバーフローも脆弱性である可能性があります。 「Secure Code」という本のセキュリティ専門家Michael HowardとDavid Leblancからの引用を引用させてください。 。 これは、コードが自動的に安全になることを意味するものではありませんが、一部の攻撃クラス-おそらくバッファオーバーフロー攻撃-を悪用するのがはるかに難しくなります。 サーバーへのDoS攻撃についても同様です。これは、メモリリークやその他のリソースが原因で発生する可能性があります。 ちょっと考えてみましょう。配列とガベージコレクターの境界の組み込みチェックだけのために、低速で機能が少なく、分解しやすい言語を使用することをお勧めします。



ここでは、DoS攻撃(サービス拒否、サービス拒否)とDDoS攻撃(分散サービス拒否、分散サービス拒否)の違いを強調する必要があります。 DoS攻撃は、原則として、サービスで「スマート」なトリックと脆弱性を使用し、少数のコンピューター(おそらく1台から)から実行されます。 たとえば、前述のように、DoS攻撃はメモリリークに基づく場合があります。 別の例は、ファイルサーバーへの攻撃で、ダウンロードされたすべてのファイルのウイルスチェックが行われます。 まず、1つのゼロで構成されるサイズが数ギガバイトのファイルが作成され、アーカイブされ(アーカイブサイズは数キロバイト)、攻撃されたサーバーにダウンロードされます。その後、サーバーはそれを解凍し、ウイルス対策ソフトウェアでチェックしようとします...明らかに設計されていない要求が非常に多いサービス。 言い換えれば、これは多数の車両から即座に実行される「正面からの」攻撃です。 DDoS攻撃から保護する方法は多数ありますが、適切に組織化されたDDoS攻撃から100%保護することは不可能です。したがって、サービス自体のパフォーマンスは非常に重要になります。処理できるリクエストが多いほど、攻撃の影響は小さくなります。 この結果、パラドックスが発生します。C#はリソース制御が優れているため、DoS攻撃の実行を大幅に複雑化する可能性がありますが、速度が遅いため、サービスはDDoS攻撃に対してより脆弱になります。



しかし、C ++での配列の境界のチェックに戻ります。 これはシステムプログラミング言語であり、追加のオーバーヘッドがあると、最終的にプログラムの生産性が低下する可能性があることを理解しています。 ただし、パフォーマンス基準は製品の最終リリースバージョンでのみ重要であることを強調する必要があります。 デバッグバージョンは、テスト例を使用してプログラム開発者の狭いサークルで動作するように設計されているため、品質を向上させ、エラーの可能性を減らすことができるさまざまなチェックおよびデバッグメッセージを含めることができます(詳細はスティーブマッコネルの本「Perfect Code」を参照してください)。 したがって、少なくともプログラムのデバッグバージョンについては、C ++ 11標準にこのようなツールが欠けていることは残念です。 ただし、gcc StackguardおよびStack-Smashing Protectorコンパイラー拡張機能(以前のProPolice)、Microsoft Visual Studio、IBM Compilerコンパイラーなど、オーバーフローエラーを検出するためにスタックを変更から保護するサードパーティ製品があることに注意してください脆弱性の悪用を複雑にします。 しかし、システムをハッキングする可能性はまだ残っています。 スタックでのオーバーフローに加えて、ヒープでのオーバーフローも可能です。これも同様に危険です。 結論:ハッキングから身を守る唯一の信頼できる方法は、正しいコードを書くことです。



Dがレッスンを学んだことを知ってうれしいです。最適化されたバージョンをコンパイルするときに無効になっているプログラムのデバッグバージョンの配列の境界をチェックするための組み込みサポートがあります。 つまり、Dは2つの世界の特質を兼ね備えています。これは、システムとアプリケーションのプログラミング言語に最適な選択肢です。 しかし、Dのセキュリティ機能はまだ始まったばかりです。 ポインターの算術演算など、潜在的に危険なメモリ演算を禁止するD言語のサブセットであるSafeDについて言及しないのは、単に間違っているでしょう。 これにより、メモリはそのまま残ります。 組み込みのガベージコレクターと組み合わせることで、この言語はC#に典型的な機能を獲得します。バッファーオーバーフローエラーとDoS攻撃は、それほど煩わしくないでしょう。 ハワードとルブランのアドバイスを少し言い換えてみましょう。潜在的に危険なコードフラグメントをDで記述し、安全で効率的でコンパイルされた言語を楽しんでください。



C / C ++コードを呼び出す機能-業界標準



Dの別の重要な機能に言及する時が来ました:オブジェクトファイルのレベルでC / C ++コードと完全に互換性があり、C / C ++で記述された関数とクラスに直接アクセスできます。 実際、標準CライブラリはD標準の一部ですが、代わりにDライブラリの対応する関数を使用することをお勧めします。これは、誰もが大量のC ++コードをDに書き換えないためです-お気に入りのC ++コンパイラで武装するだけで完了です。 比較のために、たとえばC ++で記述されたアンマネージコードからC#などで記述されたマネージコードを呼び出すことは、私の観点からはリンクよりも複雑なCOMオブジェクトを介して可能です。 確かに、C ++ / CLI標準では、マネージコードとC ++をやり取りするための高度なメソッドが追加されますが、これはMicrosoft Visual C ++コンパイラのみを使用することを意味します。



デストラクタに対するガベージコレクション



ガベージコレクションのトピックについて詳しく説明する必要があります。 「ガベージコレクションが言語に追加されると、パフォーマンスが台無しになる」というフレーズをよく耳にしました。 私はすぐにこれらの人々に尋ねたいと思う:「テストをしたか。」 システムプログラミング言語であるDは、手動のメモリ管理を使用できます(ただし、この機能はSafeDサブセットには含まれていません)。 newおよびdelete演算子とCスタイルのメモリ管理関数mallocおよびfreeをオーバーロードすると、ツールキットに表示されます。 さらに、原則として、コードの10%のみを変更することにより、パフォーマンスを90%向上させることができます(Martin Fowlerの著書「リファクタリング。既存のコードの改善」に基づきます)。 つまり、ほとんどのプログラムは、リソースを安全に処理する命令を使用して作成でき、速度に重要な小さな断片を注意深くチェックできます。 同じプログラミング言語が使用されていることを理解することが重要です。これにより、コードの作成、保守、および保守が簡素化されます。 さらに、大規模プログラムでは、C ++プログラマーが(一部のソースによると最大50%まで)メモリー管理に多くの時間を費やすため、ガベージコレクションは開発を高速化します。 そのため、ここに推奨事項があります。コードを記述し、パフォーマンスの問題をプロファイラーに任せます。これは、パフォーマンスの点で問題のあるコードの特定に役立ちます。



また、ガベージコレクションなしでは単純に正しく機能しないアルゴリズムもいくつかあります。簡単な例を挙げましょう:特定の数を象徴する抽象クラスNumberとそのサブクラス:Integer、Long、BigInt、Float、Double、Real、Complexなどがあります。プログラムのどこかに次のような行が表示されると想像してください。


数値* c = a + b;


ここで、aとbはNumberへのポインター、つまり変数の実際のタイプは不明です。 aとbがLongの場合、LongまたはBigInt(オーバーフローエラーを回避するため)、IntegerおよびComplexの場合、Complex、DoubleおよびDoubleの場合、Integer、Long、FloatまたはDouble(依存得られた小数点以下の桁数から、例えば0.5 + 0.5 = 1)など。演算子+(数値* a、数値* b)関数を正しく実装する方法を教えてください。実装の詳細な分析はこの記事の範囲外ですが、マルチ転送(特にダブル転送)の章で、Jeff Algerの本物のプログラマー向けC ++のいくつかの機能に誰もが慣れ親しむことができます。演算子+関数は、新しい演算子を使用してヒープ上にオブジェクトを作成する必要があることに注意してください。呼び出すコードはオブジェクトcの実際のタイプについて何も知ることができないため、スタック上のメモリを割り当てることができません。そのため、メモリを解放するためにガベージコレクションメカニズムが必要です。この場合、参照カウントでスマートポインターを使用できますが、基本的な制限があります。つまり、組み込みのガベージコレクション言語に置き換わるものは何もなく、C ++ 11標準は基本的な機能のみをサポートしているという事実(高度なガベージコレクションの実装は標準に含まれていません)はまったく私を喜ばせません。最後に、フランシスベーコンからの引用を思い出したいと思います。「新しい手段に頼りたくない人は誰でも、新しいトラブルを予期すべきです。」はい、突然数値の前の例に興味があれば、CLOS(Common Lispオブジェクトシステム)に注意することもお勧めします。複数のスケジューリングのサポートが既に組み込まれています。



デストラクタとガベージコレクション



次に知っておくべきこと-DにはRAII(リソースの取得は初期化)があります-C ++に典型的なリソース管理モデルですが、C#とJavaにはありません。つまり、Dにはデストラクターがあり、ガベージコレクターに関係なく呼び出されます。その結果、このパラダイムはリソースの管理を容易にします(そもそも、そのリリース)。



ご存じのように、C#とJavaはこのモデルを放棄し、デストラクタをガベージコレクション後に呼び出されるターミネータに置き換えました。後者は、ターミネーター呼び出しが長時間後に発生する可能性があるため、ターミネーターを使用してシステムに重要なリソースを解放することを不可能にします。したがって、リソースを明示的に解放する必要があります。 「しかし、情報を隠すことはどうですか?結局のところ、リソースの明示的なリリースが必要なクラスとそうでないクラスを覚えておく必要があります!エラーが表示されるのはここです」と尋ねると、あなたは正しいでしょう。これに応じて、それはC ++でありDであると肩をすくめて答えるだけです。真に、誤って記述されたプログラムの場合、リソースを解放する「いつかわからない」は「決して」よりも優れているため、モデル間に明確な選択がありますC ++およびC#/ Javaでのリソース管理は困難です。おそらくこれが、C ++とJavaの信者の間で非常に多くの議論がある理由です。



また、C#では、リソースを明示的に解放するコードをスキップした結果、ファイナライザーへの呼び出しがリソースを正しく解放できない場合があります(データが失われる、例外が発生するなど)。たとえば、Streamのサブクラスであり、ファイルストリームにバイナリデータを書き込むことができるFileStreamクラスと、(サブクラスのいずれかで)さまざまなバイナリストリームに任意のデータ(たとえば、文字列、異なる番号など)を書き込むことができるStreamWriterクラスを考えますたとえば、FileStream、MemoryStream、NetworkStreamなどのストリーム。その結果、任意のデータを任意のフローに書き込むことができ、実際にブリッジ設計パターンを実装します(E. Gamma、R。Helm、R。Johnson、D。Vlissides、「オブジェクト指向設計手法。設計パターン」)。想像してみてこれらのすべてのクラスには、パフォーマンスを向上させるために、組み込みのバッファーがあり、バッファーがいっぱいになった後にのみデータが書き込み用に送信されます(これがこれらのクラスが.NETで実装される方法です)。ここで、プログラムにエラーを追加します。プログラマはリソースを明示的に解放するのを忘れました。ガベージコレクションの後、FileStreamクラスとStreamWriterクラスのオブジェクトが使用されなくなると、それらのファイナライザが呼び出されます。しかし、.NETでのファイナリターの実行順序は定義されていません!つまり、ケースの約50%で、StreamWriterのファイナライザがバッファをファイナライズする前に、FileStreamオブジェクトのファイナライザがファイルを閉じます。 StreamWriterオブジェクトのファイナライザは、データを書き込む場所がないため、何をする必要がありますか? 2つの明らかな可能性があります。データ損失につながるものを無視するか、例外をスローするか、データの損失とプログラムのクラッシュにつながります(この例外は未処理のままになるため)。私の観点からは、例外のスローはプログラムのデバッグを簡素化するので望ましいですが、Microsoftプログラマーは私に同意しません。これらのクラスの実装では、サイレントデータ損失を好みます。さらに、そのようなエラーをコミットするために、リソースの明示的な解放をスキップする必要はありません。タイプがStreamWriterのオブジェクトのリソースを解放する前に、タイプがFileStreamのオブジェクトのリソースを解放する必要があります...結論:ガベージコレクターまたはRAIIだけでは効率的なリソース管理には不十分であるため、Dはこれらのテクノロジーの両方をサポートしています。それはプログラムのデバッグを簡単にするからです。しかし、マイクロソフトのプログラマーは私に同意しません。これらのクラスの実装において、彼らは静かなデータ損失を好みました。さらに、そのようなエラーをコミットするために、リソースの明示的な解放をスキップする必要はありません。タイプがStreamWriterのオブジェクトのリソースを解放する前に、タイプがFileStreamのオブジェクトのリソースを解放する必要があります...結論:ガベージコレクターまたはRAIIだけでは効率的なリソース管理には不十分であるため、Dはこれらのテクノロジーの両方をサポートしています。それはプログラムのデバッグを簡単にするからです。しかし、マイクロソフトのプログラマーは私に同意しません。これらのクラスの実装において、彼らは静かなデータ損失を好みました。さらに、そのようなエラーをコミットするために、リソースの明示的な解放をスキップする必要はありません。タイプがStreamWriterのオブジェクトのリソースを解放する前に、タイプがFileStreamのオブジェクトのリソースを解放する必要があります...結論:ガベージコレクターまたはRAIIだけでは効率的なリソース管理には不十分であるため、Dはこれらのテクノロジーの両方をサポートしています。このようなエラーをコミットするために、リソースの明示的な解放をスキップする必要はありません。StreamWriter型のオブジェクトのリソースを解放する前にFileStream型のオブジェクトのリソースを解放するだけで十分です。結論:ガベージコレクターまたはRAIIだけでは効率的なリソース管理には不十分であるため、Dはこれらのテクノロジーの両方をサポートしています。そのようなエラーをコミットするために、リソースの明示的な解放をスキップする必要はありません。StreamWriter型のオブジェクトのリソースを解放する前にFileStream型のオブジェクトのリソースを解放するだけで十分です...そのような場合、C ++ルールに憧れ始めます:結論:ガベージコレクターまたはRAIIだけでは効率的なリソース管理には不十分であるため、Dはこれらのテクノロジーの両方をサポートしています。これが、Dがこれらのテクノロジーの両方をサポートする理由です。これが、Dがこれらのテクノロジーの両方をサポートする理由です。



結論の代わりに



残念ながら、この記事にはDの多くの機能を確認するのに十分なスペースがありませんでした。しかし、それらを簡潔にリストしたいと思いますが、



?









最後に、プログラミングと、将来のプログラムのための適切な言語選択で、皆さんに成功をお祈りします。



All Articles