Skip to main content

THROW (ObjectScript)

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

構文

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