Skip to main content

This documentation is for an older version of this product. See the latest version of this content.Opens in a new tab

THROW (ObjectScript)

次の例外ハンドラへ明示的に例外をスローします。

Synopsis

THROW oref THROW:pc oref 

引数

引数 説明
pc オプション — 後置条件式。
oref オプション — 例外ハンドラへスローされるオブジェクト参照 (OREF)。 オプションですが、指定することを強くお勧めします。

説明

THROW コマンドは明示的に例外をスローします。例外は、システム・エラー、%Status 例外、またはユーザ定義の例外です。この例外は、%Exception.AbstractExceptionOpens in a new tab オブジェクトから継承するオブジェクト参照 (OREF) としてスローされます。THROW コマンドは、この例外を次の例外ハンドラへスローします。

THROW oref の使用には、2 つの方法があります。

  • TRY/CATCH : THROW oref を使用して、TRY のコード・ブロック内から例外を明示的に通知し、TRY ブロックから対応する CATCH ブロックの例外ハンドラに実行を渡します。

  • その他の例外ハンドラ : THROW oref を使用して、TRY ブロックにおいて例外を明示的に通知します。これにより、現在の例外ハンドラ ($ZTRAP など) がトリガされます。oref$THROWOBJ 特殊変数から取得できます。

Note:

引数なしTHROW を使用することは非推奨であり、新しいコードではお勧めしません。

システム・エラー

InterSystems IRIS は、未定義の変数を参照するなどの実行時エラーが発生したときにシステム・エラーを発行します。システム・エラーは %Exception.SystemExceptionOpens in a new tab オブジェクト参照を生成して、oref のプロパティである Code、Name、Location、Data、ならびに、$ZERROR および $ECODE 特殊変数を設定し、次のエラー・ハンドラに制御を渡します。このエラー・ハンドラは、CATCH 例外ハンドラ、または $ZTRAP あるいは $ETRAP エラー・ハンドラです。システム・エラーは暗黙的エラーであり、THROW を使用しません。

エラー・ハンドラ内において THROW を使用すると、システム・エラー・オブジェクトをさらに別のエラー・ハンドラにスローできます。これは信号再伝達システム・エラーと呼ばれます。

THROW は、実行スタックの制御を次のエラー・ハンドラに渡します。例外が %Exception.SystemExceptionOpens in a new tab オブジェクトである場合、次のエラー・ハンドラは CATCH$ZTRAP または $ETRAP のいずれのタイプでもかまいません。 それ以外の場合、例外を処理するためには、CATCH である必要があります。そうでないと、<THROW> エラーが生成されます。

引数

oref

例外オブジェクトへの参照。これは %Exception.AbstractExceptionOpens in a new tab を継承する任意のクラスのインスタンスです。システム・エラーの例外オブジェクトは、クラス %Exception.SystemExceptionOpens in a new tab のインスタンスです。ユーザ指定の例外オブジェクトは、%Status 例外オブジェクト (%Exception.StatusExceptionOpens in a new tab)、一般的な例外オブジェクト (%Exception.General)、または SQL 例外オブジェクト (%Exception.SQLOpens in a new tab) のいずれかになります。ユーザ例外オブジェクトを作成してデータを入れるのは、プログラマの責任です。

OREF の詳細は、"クラスの定義と使用" の “OREF の基本” を参照してください。

TRY ブロックからの THROW

THROW oref は、TRY ブロックから対応する CATCH ブロックに発行できます。これにより、ユーザ定義の例外が明示的に通知されます。これにより、TRY ブロックから対応する CATCH ブロックに実行が渡されます。スローされた oref は、CATCH ブロックの exceptionvar 引数として設定されます。

引数付きの THROWCATCH の例外ハンドラから発行するには、CATCH 以外の例外ハンドラにスローするか、または TRY ブロック (および関連する入れ子になった CATCH ブロック) を CATCH の例外ハンドラ内で入れ子にし、この入れ子になった TRY ブロックから THROW を発行します。

%Status 例外およびユーザ定義の例外

%Status 例外またはユーザ定義の例外をトラップするには、oref 引数として %Exception.AbstractExceptionOpens in a new tab オブジェクトに基づいたオブジェクトを指定します。例外クラスを定義してから、%New() を使用してそのクラスのインスタンスを作成し、例外情報を提供します。このタイプの例外は、CATCH 例外ハンドラで処理される必要があります。CATCH が存在しない場合、システムは <THROW> エラーを生成します。

ユーザ定義の例外では、$ZERROR の値も $ECODE の値も変更されません。これらの特殊変数のいずれかを使用するには、プログラムで SET コマンドを使用して、これらの変数を明示的に設定する必要があります。

一般的な例外

InterSystems IRIS は、THROW 引数として指定できる一般的な例外を提供します。これは %Exception.AbstractExceptionOpens in a new tab 抽象クラスの %Exception.GeneralOpens in a new tab サブクラスです。この使用法は、以下の例を参照してください。

  TRY {
       WRITE "In the TRY block",!!
       SET mygenex = ##class(%Exception.General).%New("My exception","999",,
                             "My own special exception")
       THROW mygenex
       WRITE "This shouldn't display",!
      }
  CATCH stuff {
       WRITE "In the CATCH block",!
       WRITE stuff.Name,!
       WRITE stuff.Code,!
       WRITE stuff.Data,!
       WRITE "End of the CATCH block",!
       RETURN
      }

TRY ブロック外における THROW

THROWTRY ブロック外から発行すると、InterSystems IRIS によって <THROW> エラー "<THROW>+3^myprog *%Exception.General MyErr 999 My user-defined error" が生成されます。この THROW の使用は、エラーの再通知に役立ちます。

THROW で指定されるオブジェクト参照 (oref) は、$THROWOBJ 特殊変数で保存されます。例 : 9@%Exception.General$THROWOBJ 値は、次の正常な THROW 処理、または SET $THROWOBJ="" によってクリアされます。

以下の例では、THROW は $ZTRAP の例外ハンドラに例外をスローします。

MainRou
       WRITE "In the Main Routine",!!
       SET $ZTRAP=^ErrRou
       SET mygenex = ##class(%Exception.General).%New("My exception","999",,
                             "My own special exception")
       THROW mygenex
       WRITE "This shouldn't display",!
       RETURN
ErrRou
       WRITE "In $ZTRAP",!
       SET oref=$THROWOBJ
       SET $THROWOBJ=""
       WRITE oref.Name,!
       WRITE oref.Code,!
       WRITE oref.Data,!
       WRITE "End of $ZTRAP",!
       RETURN

引数なしの THROW

引数なしの THROW は、現在のシステム・エラーを再び信号で送り、次の例外ハンドラへ制御を渡します。現在のシステム・エラーは、$ZERROR 特殊変数によって参照されるエラーです。したがって、引数なしの THROW はコマンド ZTRAP $ZERROR と同等です。

どのシステム・エラーが現在のシステム・エラーであるかは変更されることがあるため、引数なしの THROW の使用はお勧めできません。例えば、エラー・ハンドラが $ZERROR 値を変更した場合、または、エラー・ハンドラ自体がシステム・エラーを生成した場合にこれが発生する可能性があります。そのため、THROW oref を使用して、次の例外ハンドラへスローされるシステム・エラーを明示的に指定することをお勧めします。

以下の例では、%Exception.GeneralOpens in a new tab クラスのインスタンスを使用してユーザ定義の例外をスローします。ここでは、後置条件付き構文で THROW を使用する方法を示しています。この例では、Exceptions メソッドを呼び出し、引数として 5 以上の数を渡すと、例外がスローされて catch ブロックの WRITE 文が実行されます。

ClassMethod Exceptions(x As %Integer)
{
   set ex = ##class(%Exception.General).%New()
   set ex.Name = "Demo Exception",
      ex.Code = 100000,
      ex.Data = "Tutorial Example"
     try {
      write !, "Hello!,
      throw:(x >= 5) ex   // throw the exception    }
   catch err {
      write !, "x: ", ?20, x,
              !, "Error name: ", ?20, err.Name,
              !, "Error code: ", ?20, err.Code,
              !, "Error location: ", ?20, err.Location,
              !, "Additional data: ", ?20, err.Data, !
   }
   write !, "Finished!" 
}

以下の例では、InterSystems IRIS のエラー名が山括弧で囲まれ、これらの例が Web ブラウザから実行されるので、$ZCVT(myerr.Name,"O","HTML") が使用されます。多くの別のコンテキストでは、myerr.Name は必要な値を返します。

以下の例では、TRY ブロックで誕生日が生成されます。未来の日付の誕生日が生成された場合、THROW の使用により一般的な例外が発行され、ユーザ定義の例外の OREF が汎用 CATCH ブロックに渡されます。(例外をスローする日付を生成するために、この例を複数回実行する必要がある場合があります)

  TRY {
      WRITE "In the TRY block",!
      SET badDOB=##class(%Exception.General).%New("<BAD DOB>","999",,"Birth date is in the future")
      FOR x=1:1:20 { SET rndDOB = $RANDOM(7)_$RANDOM(10000)
        IF rndDOB > $HOROLOG { WRITE !,"Birthdate ",$ZDATE(rndDOB,1,,4)," is invalid"
                               THROW badDOB }
        ELSE { WRITE "Birthdate ",$ZDATE(rndDOB,1,,4)," is valid",! }
     }
  }
  CATCH err {
        WRITE !,"In the CATCH block"
        WRITE !,"Error code=",err.Code
        WRITE !,"Error name=",$ZCVT(err.Name,"O","HTML")
        WRITE !,"Error data=",err.Data
        RETURN
  }

以下の例では、ユーザ定義の引数を使用した 2 つの THROW コマンドのいずれかを発行できます。$RANDOM は、どの THROW を発行するか (ランダムな値 0 または 1)、または THROW を発行しないか (ランダムな値 2) を選択します。ブロックの実行が RETURN コマンドで終了しない限りは、コードの実行は TRY / CATCH ブロックの後に続行されます。

  TRY {
     SET errdatazero="this is the zero error"
     SET errdataone="this is the one error"
     /* Error Randomizer */
        SET test=$RANDOM(3)
        WRITE "Error test is ",test,!
     IF test=0 { 
       WRITE !,"Throwing exception 998",!
       THROW ##class(Sample.MyException).%New("TestZeroError",998,,errdatazero)
         THROW myvar
       }
     ELSEIF test=1 { 
       WRITE !,"Throwing exception 999",!
       THROW ##class(Sample.MyException).%New("TestOneError",999,,errdataone)
       }
     ELSE { WRITE !,"No THROW error this time" }
  }
  CATCH exp {
      WRITE !,"This is the exception handler"
      WRITE !,"Error code=",exp.Code
      WRITE !,"Error name=",exp.Name
      WRITE !,"Error data=",exp.Data
      RETURN
  }
  WRITE !!,"Execution after TRY block continues here"

以下の例は、システム・エラーが発生したときの THROW の使用法を示しています。THROW は、一般的に、システム・エラーを別のハンドラに転送するために CATCH 例外ハンドラで使用されます。これは、システム・エラーが予期しないタイプのシステム・エラーを受け取ったときに行われる可能性があります。これを行う場合、TRY ブロック (および対応する CATCH ブロック) を CATCH ブロック内に入れ子にする必要があることに注意してください。これは、入れ子になった CATCH ブロックにシステム・エラーを THROW するために使用されます。以下の例でこれを示します。Calculate を呼び出して除算演算を実行して、その答えを返します。考えられる結果は 3 種類です。その 1 番目として、y が任意のゼロ以外の数値の場合、除算演算は成功し、CATCH ブロック・コードは実行されません。2 番目として、y がゼロ (または非数値文字列) の場合、除算演算では、ゼロでの除算が試みられ、その CATCH ブロックにシステム・エラーがスローされます。これは、このエラーを “修正して” 0 値を返す calcerr 例外ハンドラによって捕捉されます。3 番目として、y が定義されていない場合 (NEW y)、calcerr は予期しないシステム・エラーを捕捉して、このエラーを myerr 例外ハンドラへスローします。この 3 つの結果を示すために、このサンプル・プログラムでは $RANDOM を使用して除数 (y) を設定しています。

Randomizer
  SET test=$RANDOM(3)
  IF test=0 { SET y=0 }
  ELSEIF test=1 { SET y=7 }
  ELSEIF test=2 { NEW y }
  /* Note: if test=2, y is undefined */
Main
  SET x=4
  TRY {
    SET result=$$Calculate(x,y)
    WRITE !,"Calculated value=",result
  }
  CATCH myerr {  
    WRITE !,"this is the exception handler"
    WRITE !,"Error code=",myerr.Code
    WRITE !,"Error name=",$ZCVT(myerr.Name,"O","HTML")
    WRITE !,"Error data=",myerr.Data
  }
  QUIT

Calculate(arg1,arg2) PUBLIC {
  TRY {
  SET answer=arg1/arg2
  }
  CATCH calcerr {
      WRITE "In the CATCH Block",!
      TRY {
          IF calcerr.Name="<DIVIDE>" {
          WRITE !,"handling zero divide error"
          SET answer=0 }
          ELSE { THROW calcerr }
          RETURN
      }
      CATCH {
          WRITE "Unexpected error",!
          WRITE "Error name=",$ZCVT(myerr.Name,"O","HTML"),!
      }
  }
  QUIT answer
}

関連項目

FeedbackOpens in a new tab