3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

is演算子のキャストと早期returnの組み合わせの際の注意点

Last updated at Posted at 2020-10-28

この記事で述べていること

  • is演算子でのキャストは結果がtrueになる際のみ行われます。ですが、結果に関係なくキャスト後の変数の宣言はなされます(falseの場合中身は未初期化になる)
  • また、ifステートメントの条件式内でis演算子を用いてキャストすると、キャスト後の変数のスコープはそのifを囲むブロック内となります。
  • この性質のせいで、早期returnで弾くと同時にキャストし、キャスト後の変数をその後使おうとすると怒られます。
  • そういう時はasとnullチェックを使いましょう。

説明

is演算子を使ってifステートメントの条件式内でキャストを行った場合、キャスト後の変数のスコープはそのifを囲むブロック内となります。
また、is演算子でのキャストはインスタンスの型が一致した場合のみ行われます。一致しない場合変数は宣言されますが、中身は未初期化になります(nullが入るわけでもありません)
この性質のせいで、早期returnでインスタンスの型が一致しない場合を弾いた後、キャスト後の変数を後々の処理に使おうとするとちょっと問題が生じます。

インスタンスの型チェックと早期return
public void hoge(Object obj){
  //こうしてobjのインスタンスの型が任意の型でない場合を弾いた後
  if((obj is int x) == false) return;

  //後々の処理にxを使おうとすると
  //未初期化の可能性があると言われ怒られる
  Console.WriteLine(x);

  //同名変数の再宣言も不可で怒られる
  int x = 1;
}

コンパイラから見たらintじゃない場合最初のifで弾かれてるからifの外で使っても大丈夫なんてわからないので、怒られます。
かといって変数が死んでいるわけではないので、同名変数の再宣言も不可です。怒られます。
考えてみれば当たり前の話で馬鹿らしいですが、私はこれで数十分無駄にしました。

解決策

ではどうするか。as演算子とnullチェックを組み合わせましょう。

as演算子との組み合わせ
public void hoge(Object obj){
    int x = obj as int;
    if(x == null) return;

    //怒られずにnullチェック済みのxを使って処理が可能
    Console.WriteLine(x);
}

これで解決ですね。

最後に

マサカリお待ちしてます。

参考サイト

3
2
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?