質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

4回答

5327閲覧

コンストラクタでの例外

Ojawa

総合スコア13

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

1クリップ

投稿2019/09/22 07:47

編集2019/09/22 08:24

質問

C# では、コンストラクタで例外をスローするのはお作法としてよいのでしょうか?

C++ とは異なり、GC がメモリを解放してくれるので
コンストラクタで例外を投げても、よしなに解放処理が走るため例外をスローしても問題ないのでは?と考えています。
※アンマネージリソースの確保がない場合。

以下コメントアウトしている箇所での、例外スローについて悩んでいます。
コメントアウトを解除してもよいかどうか、お知恵をお貸しいただけないでしょうか。

該当のソースコード

C#

1/// <summary> 2/// コンストラクタ 3/// </summary> 4public Score(int score) 5{ 6 // 生成されるインスタンスが 0-10 の範囲内であることを保証したい 7 // if (_score < 0 || 10 < _score) throw new ArgumentOutOfRangeException(); 8 _score = score; 9}

使用サンプル

C#

1[TestCase(-1)] 2[TestCase(11)] 3public void ExceptionScoreTest(int roll) 4{ 5 Assert.That(() => new Score(roll), Throws.TypeOf<ArgumentOutOfRangeException>()); 6}

補足

この手の質問・記事は web ページにいくつかありましたが、
賛否両論であったり、記事のページが数年前のもの、また .NetFramework のバージョンも当時と異なるため
本質問を投稿させていただきました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

FileStream Constructors

FileStream のコンストラクタは例外を投げます。

投稿2019/09/22 07:56

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2019/09/22 08:13 編集

アンマネージリソースであるファイルハンドルを確保しています。 例外を投げてはいけないという主張にはその理由が書いてあるはずです。それをよく読んで理解して使ってください。投げるべきではないケースもあるはずです。 「C++ がそうだから」というのは話になりません。無視してください。
Ojawa

2019/09/22 08:14

>>Zuishin さん いつもご回答ありがとうざいます。 FileStream 等は、アンマネージリソースを扱うので少々コストの高い例外をスローするのは処理に見合っていると思うのですが、 マネージリソースのインスタンス生成時で値範囲チェックのために例外をスローするのは、 コストに見合わない?とも考えています。生成の度に catch 処理もコードに埋めなくてはならないので。 しかし内部的に、-1 のような異常値を _score に持たせるのも考えもので・・・。
Zuishin

2019/09/22 08:18

ケースバイケースだと思いますが、範囲チェックのための例外送出はありです。 速度が気になるなら、コンストラクタに渡す前に初期値のチェックをしてください。
Ojawa

2019/09/22 08:29

> 速度が気になるなら、コンストラクタに渡す前に初期値のチェックをしてください。 こちら非常に参考になりました。 null チェックなどでも、null が入ることがありえないケースにおいてはチェック処理を記述しないため 例外でも同様のことが適用できそうです。 ありがとうございます。
Zuishin

2019/09/22 08:38 編集

コンストラクタでのチェック処理自体は書いておいた方がいいと思います。そして不正な値の場合は例外を起こすのが良いと思います。思わぬバグが入ったときにみつけやすくなります。 生成前と生成後と二重にチェックすることになりますが、それは許容するべきものだと思います。
guest

0

ベストアンサー

コンストラクタで例外を投げても問題ないと思いますが,

コンストラクタをprivateにして,代わりにインスタンス生成する用のstaticメソッドを用意するとかすればそこで引数チェックしてからコンストラクタを呼ぶことができますから,コンストラクタ内では引数チェックを書かずに済み,リソース関係の心配事も減るかもです.(インスタンス生成するための記述が変わってしまいますが)
何なら,例外創出ではなくnullを返すとかも(やりたければですが)できます.

投稿2019/09/23 02:13

fana

総合スコア11658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Ojawa

2019/09/23 07:29

>>fana さん ご回答ありがとうございます。 シングルトンや、Factory パターンの Create などで生成する時に使用していましたが あえて private コンストラクタにしていることが使用者からすると気軽にインスタンス化出来ないクラスと明示できるため良さそうだと思いました。
guest

0

C++ とは異なり

そもそも論として、C++でもコンストラクタから例外を投げるのが適切なときがあります(例外を投げずに対応しようとすると、呼んだ側に中途半端なオブジェクトを返してしまうことになります)。

一方で、C++のデストラクタで例外を投げるのは、基本的によくありません。

投稿2019/09/22 08:31

編集2019/09/22 08:33
maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Ojawa

2019/09/23 08:46 編集

>>maisumakun さん C++ でコンストラクタから例外を投げるときが適切な場合があるとのことで 私自身調べてみたのですが、該当するケースを見つけることが出来ませんでした。 基本的には、[TotW #42](https://abseil.io/tips/42) のパターンを活用しているのですが、 コンストラクタから例外を投げることが適切なケースが気になります。 該当ケースがどのようなものか教えていただけないでしょうか。
maisumakun

2019/09/23 08:49

極論、newをプリミティブ型に使った場合でも、メモリ不足だと処理系がstd::bad_allocを飛ばします。
Ojawa

2019/09/23 08:55

自作クラスの場合は、あまりケースとしてない認識でよいでしょうか?
guest

0

C# では、コンストラクタで例外をスローするのはお作法としてよいのでしょうか?

「コンストラクタだから」という理由で御法度にはならないでしょう。
ただし、「コンストラクタは戻り値を返せないから」という理由で例外処理を使うのは良くないと思います。
「if文」と「例外処理」は正しい使い分けが必要です。

賛否両論であったり、記事のページが数年前のもの、また .NetFramework のバージョンも当時と異なるため
本質問を投稿させていただきました。

この辺の事情は、初期バージョンの頃から変わっていませんので、他の記事を参考にしていただいても良いと思います。

投稿2019/09/22 08:28

nskydiving

総合スコア6500

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Ojawa

2019/09/23 08:57 編集

自分のやりたいことが上手く実現できないため、妥協案として使用するのはいけない。 肝に命じさせていただきます。 > この辺の事情は、初期バージョンの頃から変わっていませんので、他の記事を参考にしていただいても良いと思います。 こちら情報ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問