33

PHP では、無効なキーに対して 2 つのSPL例外を定義しています。

OutOfRangeException: 無効なインデックスが要求されたときにスローされた例外。これは、コンパイル時に検出する必要があるエラーを表します。

OutOfBoundsException: 値が有効なキーでない場合にスローされる例外。これは、コンパイル時に検出できないエラーを表します。

PHP はコンパイル済み言語ではないため、コンパイル時と実行時の区別が奇妙に思えます。そのため、どの例外をいつ使用するかを理解するのが難しいと感じています。

現在、私の理解では、配列がキーとして渡された場合など、キーが根本的かつ本質的に不正な形式である場合は
...をスローする必要があります。 ...キーは一般的に問題ないが、いくつかの境界内にない場合、たとえば、渡されたが最大キーである場合。OutOfRangeException
OutOfBoundsException10050

その理解は正しいですか?

4

6 に答える 6

27

PHP には古典的な「コンパイル時間」(または、その点について多くの静的チェックを行うコンパイラ) がありませんが、私は「コンパイル時間」を「コードを書くときに間違ったかなり静的なもの」と「」として扱います。実行時」を「私のロジック、入力、または検証はある時点でオフになっていました」として。

したがって、私の提案は、次のように扱うことです。

"Compile Time" / "OutOfRangeException": エラーは、ソース コードでいつでも修正できます。ロジックがなくても、ロジックがほとんどなくてもかまいません。

私はいつも 1 から 10 までの数字を取り、あなたは 11 を入れます


"Run Time" / "OutOfBoundsException": エラーは、実行時の誤った使用によるものです。

あなたは私を作成し、1 から 5 までの値を取り、次に 7 を入れるように言いました。計算しません。

また

必要なようにそこに配置しなかったため、そこにないインデックスを要求します


サンプル:

SplFixedArrayOutOfBoundsExceptionはサイズが動的であり、実行時に可能性があるため、 a のようなものCalender::getMonthNameがスローされると予想されますOutOfRangeException。また、月の数は「コンパイル/書き込み」時に確実に固定されるため、 SplFixedArray が an をスローすることを期待します。

配列オブジェクトのサンプル:

$array が、OutOfBoundsExceptionこれらの状況でスローできる ArrayAccess を実装するオブジェクトであるとします。

$array['bar'];
$array[7];

値は ArrayAccess に期待できるものですが、SplFixedArray(5) の場合は意味がありません。代替案は、DomainExceptionまたは多分RangeException

これらのOutOfRangeException場合:

$calendar->getMonth(15);

配列または新しいクラスを配置すると、通常、プログラマーによる単純な「ああ、間違った変数を入力しました」エラーが原因で発生するコードに、より大きな論理上の欠陥が間違いなくあります。(おそらく好ましい)代替手段はUnexpectedValueExceptionand good oldInvalidArgumentExceptionです。

次のような場合:

$array[array()];
$array[new StdClass];

代替例外のいくつかは、より適しているようです。

Java 開発者は追加の問題に対処する必要があるため、例外が常に適用されるとは限らない場合に使用する Java の世界との比較。

チェックされた/チェックされていない例外。多くの人が、実行時例外ではないものはすべて Java での使用が非常に限られている/内部であまり使用すべきではないと主張しているため、これらの名前は本来の意味と意図の一部を失っています。

于 2011-11-22T15:10:03.693 に答える
11

これに対する私自身の見解は次のとおりです。

LogicException

アプリケーションのプログラミング/アセンブル時の間違いなど、開発者が犯した間違いに使用します。これらは、開発者が UnitTests を実行しているときにキャッチされることを願っています (これはコンパイル時間に相当します)。これらの例外は、ソフトウェア自体のエラーであるため、本番サイトで発生することはありません。

RuntimeException:

ユーザーが行ったミス、または実行時にアプリケーションに無効なデータが入力されたために発生したミスに使用します。これらは、予測可能なエラーですが、UnitTests で完全に防止することはできません。たとえば、本番サイトで発生する可能性があります。これらの例外は、不適切な使用法またはプログラミング エラーが原因である可能性があります。

OutOfBounds

IMO は事実上、ウィキペディアがRange of an Array in Range in Computer Programmingとして定義しているものです。つまり、

配列が数値でインデックス付けされている場合、その範囲は配列の上限と下限です。プログラムが範囲外の配列要素にアクセスしようとすると、環境によっては、警告、致命的なエラー、または予期しない動作が発生します。

つまり、インデックスが [0,1,2] の配列がある場合、[0,1,2] 以外は範囲外です。Bounds は他のデータ タイプにも適用できることに注意してください。たとえば、5 文字の文字列の 7 番目の文字にアクセスしようとすると OutOfBounds になります。

OutOfRange:

これはタフなクッキーです。C++ では、 OutOfRangeは LogicException を拡張する一般的な例外です (PHP と同様)。与えられた例がPHPコードに簡単に変換できるかどうか、または上記のコンパイル時間の定義が不明です。主な理由は、最初に a を初期化しnew Vector(10)、すぐにアクセスしようとする人がいないためat(20)です。

Java では、数学的な意味で RangeOutOfRangeを参照しているようです

関数の範囲は、可能なすべての x 値を関数に代入したときに得られる関数の可能な y 値です。

私が見つけた参考文献の 1つには、RuntimeException を拡張したものがあります。そのため、他の言語を調べることは、この謎を解決するのに役立たないと思います。一般的な SPL 例外に関する未解決のバグ レポートもあり、次のように述べています。

  • OutOfRangeException (値が範囲外) は LogicException です。次のようにする必要があります: RuntimeException

しかし、これが正しければ、OutOfRange は DomainException とどう違うのでしょうか? そして、あなた自身の定義が正しい場合、OutOfRange は とどのように違うのInvalidArgumentExceptionでしょうか?

簡単に言えば、何OutOfRangeExceptionのためにあるのかわかりません。

于 2011-11-22T16:46:57.850 に答える
4

あなたの質問への答えは私にもかなりとらえどころのないです。ただし、ここで考慮すべきことがいくつかあります。

  • 有効な配列キーを期待しているときに配列が渡される場合、InvalidArgumentExceptionそれは適切な引数タイプではないため、配列も渡されます。
  • DomainException配列は配列キーのドメインにないため、をスローすることもできます。
  • PHPでは、静的バインディングが遅いため、通常、コンパイル時に型を検出できません。それらは、実行時への変数のバインドを意図的に遅らせます。

この状況に対処する方法:

  • InvalidArgumentException引数が正しい型ではない関数に変数が渡された場合は、をスローします。配列を操作するときも、これを行います。
  • 渡されるべきではないときに渡されたInvalidArgumentExceptionifをスローします。nullnullは入力されないので、これは本当に多くのことになる可能性があります。エラーコードのチェックを簡単にするために、私は単に無効な引数に固執します。
  • OutOfBoundsExceptionあなたが提案したように、インデックスが正しい範囲にないときにスローします。
  • BadFunctionCallExceptionユーザーが指定したパラメーターとしての関数の形式が正しくない場合にスローします。内部の構造が配列である場合、それを変更する関数を渡すことができるのは理にかなっているので、これはときどき発生します。

通常、これら3つの例外だけを使用して、特別なリソースの外部で発生するすべてのエラーを表すことができます(ネットワークおよびデータベース接続は特別なリソースになります)。3つ目はより頻繁に発生しているようですが、主に前の2つを扱ったばかりです。

于 2011-11-19T17:34:12.700 に答える
4

それは非常に簡単です:

OutOfRangeは、「要求されたキーが、コードで定義されたセットのインデックス内にない」ことを意味します。

OutOfBoundsは、「要求されたキーが、読み込まれた構成によって定義されたセットのインデックス内にない」ことを意味します。

于 2013-12-09T22:47:08.770 に答える
2

The confusion in this case comes from a couple of factors. First, PHP is in fact compiled into bytecode. There are several execution environments where this compiled form persists in a relatively permanent form on the server. However, the OutOfRangeException/OutOfBoundsException issue is not about that, it's about a categorization error made by the people who documented these specific exception classes.

Since PHP is dynamically typed, it's often impossible to actually check ranges and even types at compile time. The manual states that OutOfRangeException should be raised at compile time and OutOfBoundsException should apply at runtime, which is an erroneous distinction to make in this context.

Both manual entries use unclear language of what an illegal index means, but looking at the usage of their parent classes gives some clues: LogicExceptions are extended by classes like DomainException, InvalidArgumentException, and LengthException, whereas Runtime exceptions are things such as UnexpectedValueException, OverflowException and UnderflowException. From this pattern one can infer that OutOfRangeException should probably be applied to illegal key types, and OutOfBoundsException should apply to index values that are of the correct type but are not within the bounds of their container.

There was some discussion on the PHP dev list about these categorizations being wrong, but the issue goes deeper than that. In practice, both exceptions can only actually be are raised at runtime. You can use the vagaries of the documentation to squeeze out a distinction between invalid key types and invalid index values, but at this point we're talking about a bug in the PHP documentation.

于 2011-11-28T23:18:04.030 に答える