C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

C#の例外処理

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■98257 / inTopicNo.1)  C#の例外処理
  
□投稿者/ Megumi (3回)-(2021/10/25(Mon) 12:46:18)

分類:[.NET 全般] 

 以下のコードではフォームに貼り付けた Pb(PictureBox)に画像が読み込まれていないと例外が発生します。
private void BtnTranslation_Click(object sender, EventArgs e)
{
  Bitmap canvas = new Bitmap(Pb.Width, Pb.Height);
  Graphics g = Graphics.FromImage(canvas);
  Image img = Pb.Image;
  g.TranslateTransform(120, 0);//ワールド変換行列を右に平行移動する
  g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height));
  g.Dispose();
  img.Dispose();
  Pb.Image = canvas;
}

 そこでネット上の例外処理を見て例外処理にチャレンジしているのですが、なかなかうまくいきません。以下のコードではコンパイルエラーになります。適切な方法を教えていただけたら幸いです。

private void BtnTranslation_Click(object sender, EventArgs e)
{
  Bitmap canvas = new Bitmap(Pb.Width, Pb.Height);
  Graphics g = Graphics.FromImage(canvas);
  Image img;

  try
  {
    img = Pb.Image;
    g.TranslateTransform(120, 0);
    g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height));
  }
  catch (Exception err)
  {
    MessageBox.Show(err.Message);
  }
  finally
  {
    g.Dispose();  //これは OK なのに
    img.Dispose(); //現在のコンテキストに img という名前は存在しないコンパイルエラーが出る!
    Pb.Image = canvas;
  }
}

引用返信 編集キー/
■98258 / inTopicNo.2)  Re[1]: C#の例外処理
□投稿者/ 774RR (875回)-(2021/10/25(Mon) 13:04:24)
とりあえず using に置き換えてみよう
https://divakk.co.jp/aoyagi/csharp_tips_using.html
引用返信 編集キー/
■98259 / inTopicNo.3)  Re[1]: C#の例外処理
□投稿者/ 魔界の仮面弁士 (3195回)-(2021/10/25(Mon) 13:19:26)
No98257 (Megumi さん) に返信
> 以下のコードではフォームに貼り付けた Pb(PictureBox)に画像が読み込まれていないと例外が発生します。

NullReferenceException は例外処理で拾って処理するものでは無く、
開発者側で「そもそも発生させないように気を配る」類の代物なので、
この場合は「Pb に画像が読み込まれているかどうか」を調べるべきかと思います。


 Bitmap canvas = new Bitmap(Pb.Width, Pb.Height);
 Pb.Image = canvas;
 Image img = Pb.Image;
 if (img != null) // 画像が読み込まれているか?
 {
  using (img)
  using (Graphics g = Graphics.FromImage(canvas))
  {
   g.TranslateTransform(120, 0);//ワールド変換行列を右に平行移動する
   g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height));
  }
 }


> finally
> {
>  g.Dispose();  //これは OK なのに
>  img.Dispose(); //現在のコンテキストに img という名前は存在しないコンパイルエラーが出る!
>  Pb.Image = canvas;
> }

んんん……!? 『img という名前は存在しない』というエラーではなく、
『未割り当てのローカル変数 'img' が使用されました。』ではありませんでしたか?

g 変数の方は、代入行為が try 句の外で行われているので、
g.Dispose() に到達した時点では、g が初期化済みであることが明確です。

一方で img 変数は、try 句の「img = Pb.Image;」という代入行為が失敗していた場合において、
変数の中身が、null さえもセットされていない状態ということになります。
そのようなオブジェクトを操作することは許可されないため、未割当を示す CS0165 エラーになるはず。
引用返信 編集キー/
■98260 / inTopicNo.4)  Re[2]: C#の例外処理
□投稿者/ Megumi (4回)-(2021/10/25(Mon) 14:41:59)
No98259 (魔界の仮面弁士 さん) に返信

> NullReferenceException は例外処理で拾って処理するものでは無く、
> 開発者側で「そもそも発生させないように気を配る」類の代物なので、
> この場合は「Pb に画像が読み込まれているかどうか」を調べるべきかと思います。

 すばやい回答まことにありがとうございました。そういうものなのですね。


> んんん……!? 『img という名前は存在しない』というエラーではなく、
> 『未割り当てのローカル変数 'img' が使用されました。』ではありませんでしたか?
 その通りでした。

 実は一週間ほど前、Visual Studio 2019 をダウンロードし、手探り状態で動かしています。プログラミングは20年ぶりくらいですので完全な浦島状態です(笑)。アドバイスは大変助かります。774RRさんにもお礼申し上げます。
解決済み
引用返信 編集キー/
■98261 / inTopicNo.5)  Re[3]: C#の例外処理
□投稿者/ 魔界の仮面弁士 (3196回)-(2021/10/25(Mon) 15:33:04)
No98260 (Megumi さん) に返信
>>この場合は「Pb に画像が読み込まれているかどうか」を調べるべきかと思います。

すみません! 順番が逆でした…。

// 誤
 Bitmap canvas = new Bitmap(Pb.Width, Pb.Height);
 Pb.Image = canvas;
 Image img = Pb.Image;
 if (img != null)

// 正
 Bitmap canvas = new Bitmap(Pb.Width, Pb.Height);
 Image img = Pb.Image;
 Pb.Image = canvas;
 if (img != null)


>  すばやい回答まことにありがとうございました。そういうものなのですね。
開発者が気を付ければ防げる例外としては、
NullReferenceException 以外にもこのようなものがあります。

「0 で除算しようとした場合」の DivideByZeroException や、
「配列のインデックスに、範囲外の添字を指定した場合」の IndexOutOfRangeException、
「引数指定のミス」による ArgumentOutOfRangeException や ArgumentNullException も同様に

これらのエラーは、そもそもそういうデータを受け渡ししてしまっていること自体が
そもそも呼び出し側のコードのミスなので、例外処理で対処するのではなく、
呼び出し元のプログラムを見直すことが必要です。


一方、明示的に catch すべきものとしては、ファイルの入出力や、データ通信などの例外があります。

これらは「権限不足」「空き容量不足」「通信障害」「タイムアウト」
「パスワードの有効期限切れ」などの要因で失敗することがあるため、
事前に開発者が気を付けるだけでは完全には防ぎきれません。
そのため、例外処理を加えて、その中で追加の処理を行います。

そして、その catch 句の中で何をするかは開発者次第。たとえば…
 ・続行不可能な例外だったので、エラー内容をログに残し、アプリ自体を終了する
 ・ファイルの保存に失敗したので、別の保存先をユーザーに問いかけなおして再実行する
 ・失敗したデータはスキップして、次のデータの処理を続行する
 ・処理全体をキャンセルし、エラー表示してから、実行前の状態に復元する
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ