ふらっと C#,C♯,C#(初心者用) Part142
■ このスレッドは過去ログ倉庫に格納されています
!extend:checked:vvvvv:1000:512
次スレを立てる時は↑を2行冒頭に書くこと(1行分は消えて表示されない為)
「どんなにくだらないC#プログラミングやVisual C#の使い方に関する質問でも誰かが優しくレスをしてくれるスレッド」です。
他のスレッドでは書き込めないような低レベルな質問、
質問者自身なんだか意味がよく分からない質問、
ググろうにもキーワードが分からないなど、勇気をもって書き込んでください。
内容に応じて他スレ・他板へ行くことを勧められることがあります。ご了承下さい。
なお、テンプレが読めない回答者、議論をしたいだけの人は邪魔なので後述のC#相談室に移動して下さい。
C#に関係の無い話題や荒らしの相手や罵倒レスはやめてください
>>980を踏んだ人は新スレを建てて下さい。
>>980が無理な場合、話し合って新スレを建てる人を決めて下さい。
■関連スレ
C#, C♯, C#相談室 Part93
http://mevius.5ch.net/test/read.cgi/tech/1492818720/
■前スレ
ふらっと C#,C♯,C#(初心者用) Part141
http://mevius.5ch.net/test/read.cgi/tech/1544839627/
■コードを貼る場合は↓を使いましょう。
http://ideone.com/
https://dotnetfiddle.net/
■情報源
https://docs.microsoft.com/ja-jp/dotnet/standard/class-libraries
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/index
https://docs.microsoft.com/en-us/dotnet/standard/class-libraries
http://referencesource.microsoft.com/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:----: EXT was configured ネタじゃなくて本気で変な誤解してるのか...
メソッドの途中で行が変わると別のスレッドで実行されるとかそんな言語怖くて使えないよwww お前は勘違いしてる
GUIとCUIで仕様が違ってる await/asyncは単なるTask非同期処理を簡易的に書ける糖衣構文
次にawaitの次をどのスレッドになるかはその時の状態次第
GUIではそれでは困るのでデフォルトで同じスレッドが処理をするようにしてあるだけ 訳のわからん勘違いをしてるのはどっちだよ
自信満々で馬鹿じゃないマジで 勘違いをしているのは俺の方だった...
申し訳ないですw 同じスレッドに戻ってきてもらうのに、簡単な方法ってないのかな・・・・ >>505
>>490を見るに、コンソールアプリで特定スレッドで処理したいみたいだけど、どういった理由?
GUIなら、時間がかかる処理は別スレッドで、画面更新は絶対にUIスレッドで、といった使い分けがあるけど
CUIで特定スレッドを意識する理由がちょっと思いつかないんだ >>506
WebAPIサーバを作りたく、その中で扱うデータについてトランザクション処理みたいなことをしたかったんです
通信関連でAwaitが多用されている中でも、データのロックをできるだけ減らしたい、またうっかりミスしてロック外に出ないでほしいと思ったんです >>507
それを聞いても、「特定スレッドで絶対に処理したい」が主目標にはならない気がする
「ロックにReaderWriterLockSlimを使っていて、ロック取得と解放は同じスレッドで行う必要がある」のような状況ならまだ分かるんだけど
もしもこの状況であるなら、SemaphoreSlimでロックするようにすれば、WaitOneAsyncで待つスレッドと、Releaseするスレッドを別にできる(=間でawaitできる)
万一本当に何か理由があって特定スレッドで処理を続けたいのなら、Taskをawaitするのでなく.Wait()で待つようにすれば、スレッドは切り替わらなくなる
> うっかりミスしてロック外に出ないでほしい
これが「ロックを取得したけど、解放を忘れる」ことを指すのであれば
try {} finally {} や、ラップクラスを作ってIDisposable実装してusing() {} するのが対策になるかもしれない
取得と解放がメソッドを跨いだりするなら面倒くさくなるけど…… https://ideone.com/TM1zJh
if (ob.volume == volume)この部分なのですが
左辺は引数で取ったobのメンバ変数であることは分かるのですが右辺はどのメンバ変数なんでしょうか?
入門書のコードなのですが… 19行目にも同じ構造があるけどそっちはすんなり入ったんだろうか >>510
メソッドを呼び出したob1のメンバってことですかね?
理解できました。ありがとうございます コンストラクタ内で例外をthrowするのはご法度ですか? >>514
ご法度ではないし、むしろインスタンスを正しく構築できないなら積極的にthrowしてほしい
例えばStreamReader(String)の場合、ArgumentException系列から
FileNotFoundExceptionやDirectoryNotFoundExceptionのIOException系列までthrowする 悪いとは言わないけど、最近はあまりコンストラクタで例外投げるような処理やらなくなったなあ
何故かと考えたら、async/awaitのせいだと気付いた
コンストラクタではawaitできないから、昔みたいにコンストラクタでファイル読んだりするのはほぼ無くなった あとDIと相性が悪い
DI使ってると、コンストラクタで例外投げたらそもそもアプリが起動しない ドキュメントもコンストラクタで投げる可能性のある例外一覧が必要になるけど
実際あげきれなくて手薄になりがち
そうなると設計できない
例外の種類でその後の動作をハンドリングしたいときに動かしてみて
キャッチの種類を分けるしかない
仕様書に書いてあるこのエラー出せないんすけど?
このときの例外増やしてもらえます?
→入れた引数から判断できるでしょ?とかキチガイかよって >>519
例外の種類を完全に把握できないのはコンストラクタに限ったことではないだろ >>520
そもそも例外嫌いなんよ俺
ビジネスロジックだとほぼ全部把握しないといけないのに
丸っと渡されると困るだけじゃん その例外を全部把握しなきゃいけないというのがアホな考えなんだよ
予期できないのはExeceptionとしてまとめてキャッチして処理しとけばなんの問題もないね >>522
設計書になんて書くん?
俺んとこ例外使うなら設計書に書いてない例外出しちゃうと大変なんだよ
MSのドキュメントも全部はねーし
マジ厄介
でもお客の言い分もわかる気がするんだよね
流石に何が来るかわかりませんってのはどうなの?
って思う 例外の発生要因なんてあらゆるものがあるんだから全部明示しろというお客の主張が不条理
設計書に例外全部明示しろとか要求されたことないね 規約が足かせになってる場合は無視したほうがいい
スキル低い人が大昔に作った規約かもしれないし
例外は復旧可能かつ復旧したいものだけキャッチして対処
それ以外はアスペクトでまとめて処理すればいいよ >>529
.NET Frameworkクラスもコンストラクタで例外投げるのに? >>529
C++のその説は迷信だけど、C#では事実としてawaitができないという重大な制約があるからなあ
コンストラクタで例外を投げてはいけないわけではないが、そもそも例外を投げる可能性のあるような処理をコンストラクタでやらせることができるケースが少ないのは間違いない もちろん、ArgumentNullExceptionのようにバグを検出してアプリを落とすことを目的とする例外は別だよ
そういうのを除けば、例外を投げうる処理ってのはだいたいIOを含んでいてawaitが必要になるケースが多い いまだにオブジェクト倶楽部のをベースにしたC#コーディング規約なのかな
10年くらい前の時点でも悪評ぷんぷんだったのにどれだけ時代遅れなことしてるんだ
コーディング規約作ってる奴のスキルが低い/古すぎ/多言語の知識しか持ち合わせてなくて
クソな規約になってることはよくある
コンストラクタで例外吐くのが望ましくないのはC++の話であってC#ではそんなこと全然ない
例外すべて列挙しなきゃいけないのはJavaの話であってC#にもそれを持ち込むのはナンセンス
でも大抵規約のクソさ加減と規約作成者・組織の老害度は比例するんだよな
指摘しても直ることはないだろうから「これはクソなコードだ」と自覚を持ったうえで
規約通りのコードを書くしかない >>527
それって制御できないって言ってるんだよね?
その時はtry catchで握り潰せばいいんだけど
君はどうなればいいと思ってるの?
ある日例外が起きてアプリが止まっちゃってもそれは時代の流れでしょうがないと思ってるってこと? >>534
予期せぬ例外が起きたら発生箇所のスタックトレースを表示させてバグ修正に役立てるよ
客もその画面キャプチャを送ってくれる
Execeptionにはそういうデバッグに役立つ情報入ってるからマジ便利だわ コンストラクタで例外を出すのが妥当なら出すべきだ
しかし、例外を出すような責務は得てしてファクトリやリポジトリなど外部のクラスが担うことが多い傾向にある
なので正確に言うと、オブジェクトの生成という責務を分離してない汚いプログラムはダメだ、なんだけど
それが誤って拡散した結果、コンストラクタで例外を出すプログラムはダメだ、に拡大解釈されてしまったのだろう
// コレは生成責務が分離されてないからダメだ
class Hoge {
public Hoge(int id) {
var dto = DB.FindHoge(id); // 例外なげる
m_id = id;
m_name = dto.name;
}
// コレは責務が分離されてるからOK
class HogeRepository {
public Hoge Find(int id) {
var dto = m_db.FindHoge(id); // 例外なげる
return new Hoge(id, dto.name); // 実装次第で投げたり投げなかったり
}
// コレもOK 例外投げるが責務としては妥当
class Hoge {
public Hoge(int id, string name) {
if (id < 0) throw new BadHogeFormat("id");
if (UTIL.NotMatch(@"^H\d{8}$", name)) throw new BadHogeFormat("name");
m_id = id;
m_name = name;
} >>533
> コンストラクタで例外吐くのが望ましくないのはC++の話であって
そんな話は聞いたことないが? C+の話は
C+のコンストラクタとデストラクタの言語仕様をよく理解してない奴の誤解だから
もともと正しくない >>539
お前はさっきから何の言語の話をしているんだ? ダメも糞も引数が不適切なら例外投げるしかないねそもそもw
もちろん(注意喚起とか)何らかの意図を持ってあえてコンストラクタではなく
ファクトリーメソッドやTryCreateXxxxにする方法もあるけど、
少なくとも誰が考えても引数が不適切なら例外発生が予見できるなら
コンストラクタで例外投げて何も問題ない どこならokとかngとかじゃなくて例外が発生したなら吐かなきゃ駄目
例外の前提を変えちゃ駄目 >>543
基本的になし
デストラクタの意味がなくなるから デストラクタって解放し忘れたアンマネージドリソースの解放をするためにある奴でしょ?
ただそれだけの処理に例外とか要る? >>547
どんな想定かわからないし入れたい人は入れればいいんじゃないの C#のデストラクタは実行タイミングが不明な上に
他でキャッチできないからそのままクラッシュする事になるが
それが目的なら デストラクタであろうと例外が発生したなら吐くべき
デストラクタで例外なら大体最終的にアプリ落とす結果になるだろうけど
普通に設計すりゃまずデストラクタで例外が必要にはならんとは思うが そりゃどこでも例外が出りゃ吐くべきだろ。デストラクタで出た例外は握りつぶせとでもいうのかよ デストラクタの例外は運用に入ったらログ吐いて握り潰すしかない
開発中にどれだけ発見しきれるかが勝負 馬鹿しかいないのかな
デストラクタで例外をキャッチすべきかじゃなくて
デストラクタで例外を投げるべきかだろ どうみても例外をデストラクタで握りつぶすなんて話はしてない
デストラクタで挙動がおかしな場合そこから自前で例外を投げるかどうかだろ
どうしてこんな前提すらわからないのか? デストラクタで例外投げるのは出来るけど
デストラクタの呼び出し元はファイナライザースレッドになる故
デストラクタ以外の場所でキャッチして
ログ記録したりは出来ないが、よろしいか? ところで、C#ってコンストラクタで例外吐いたとき、インスタンスは生成されて戻されるの?
そのインスタンスのデストラクタは(実装してればどこかで)実行されるの? >>554
お前黙ってろよ…
> デストラクタで挙動がおかしな場合そこから自前で例外を投げるかどうかだろ
そんな話は>>545-546で既に終わってる
今の話は例えばデストラクタでファイルクローズした時そのメソッドで例外送出されたらどうするかって話な
> どうしてこんな前提すらわからないのか?
わかってないのはお前だけ >>556
> ところで、C#ってコンストラクタで例外吐いたとき、インスタンスは生成されて戻されるの?
されない
> そのインスタンスのデストラクタは(実装してればどこかで)実行されるの?
されない ファイルクローズなんてデストラクタの仕事じゃないからクラス設計が間違ってる
もしそうせざるを得ない理由があるならアプリ終了するだけ
アプリ終了されて困るなら正しくクラス設計すればいい >>559
例えばの話してんだからそこに文句付けるのはお門違い 年甲斐もなく疲れた
お前らこんな所で何をやってんだ青瓢箪か? ここでは例外の話でドンパチ
よくのぞいてるVBAスレでもOn Errorの話でドンパチ
どちらを見てるのかわからなくなってくる >>559
> アプリ終了されて困るなら正しくクラス設計すればいい
具体的に書けないなら黙ってろってw デストラクタの中でファイル操作やクローズするのは間違ってるな
そこで例外でたらどうしようもない
ログ取るのも同じ メンバ変数を仕様上どうしてもDBから引っ張ってくるデータで初期化するしかなく、
コンストラクタ内でDB処理異常時に例外を吐く処理があります。
この場合コンストラクタ内では何もせず、インスタンス生成後にInit()のようなメソッドを
呼び出してもらうほうが使う側は楽でしょうか? そもそもC#でデストラクタに処理を書くこと自体が基本ありえないと思うんだけど・・・
リソースの解放なら(まともな構造のソースであれば)Dispose時に済ませるだろうし
デストラクタにわざわざ処理を書いて、しかもその処理が例外を引き起こすパターンって
具体的にどんなのがありうるんだ? >>566
コンストラクタで例外を吐いてください。 >>566
Init()を呼び忘れて使うリスクが出てくるので、インスタンス生成時に済ませたい派
ただDB関連では >>531-532 が言うように非同期処理をしたいだろうから
「コンストラクタはprivateにして、public staticなasyncファクトリを提供」が良いと思う
インスタンス生成時に例外出る場合だと変数の宣言と初期化が分離するけど、C#だと初期化し忘れはエラーになるから許容範囲じゃないかな
Foo foo;
try { foo = CreateFoo(); }
catch(BarException) { 何か復帰処理 }
// 以下fooを使った処理 器が小さい奴はすぐ引っ込みが着かなくなるから困ったものだ >>569
MSがデストラクタからDispose呼んでるんだがw
// Free any unmanaged objects here.
で例外が発生するケースをどう扱うのか具体的に添削してやってくれ
https://docs.microsoft.com/ja-jp/dotnet/standard/garbage-collection/implementing-dispose >>566
>>537の考え方が正解
そういう時はファクトリーを使うという考え方が世界標準 >>572
どう扱うも何もアプリ終了させろってだけだが?
ハンドリングすべきではないものをどうこうしよとしないで >>566
上にも書いたけど、あえてコンストラクタではなくstaticなTryCreateHogeみたいなのだけ提供して
注意喚起する方法もあると思うよ
>>567
デストラクタの存在理由はClose/Disposeを忘れた場合のフェイルセーフなんで
アンマネージドな共有リソースを占有するオブジェクトの場合はほぼ必須だし、
例外を投げるかどうかはともかく、デストラクタの中で例外的な事態が
発生することも普通にありえるとは思う。(例えばデバイスのクローズに失敗) どんなに丁寧に処理したって完全に例外を対応するなんてことは不可能
599の最後でちゃんとやれば良いokみたいに書いちゃったのが良くなかった
ちゃんとやったって無理なことはある >>577
何がダメ?
フェイルセーフって意味分かりますか? 無関係だけど一応答えるよ
フェイルセーフって言うのは失敗しても安全な状態に落ち着くこと
例えば信号が壊れても青信号になるんじゃなくて赤信号になるような設計
ファイルクローズは別にフェイルセーフの概念と関係ない
tryのfinallyはフェイルセーフじゃないよ >>574
ああ、お前じゃ無理だったな、すまんw
> アプリ終了されて困るなら正しくクラス設計すればいい
とほざいてた>>559、出てこいやー リソースのライフタイムの管理とリソースを使用して何かする責務を別の責務として分離したほうがいい
リソースの取得だけを分離する場合はファクトリーパターンが使われる
ただしこの場合はリソースを閉じる責務とリソースを使用する責務が同じクラスに混在してしまう
結果としてデストラクタでの例外といった問題が連鎖して発生する
これに対応するためにはファクトリーアイソレーションパターンを使う
このパターンならリソースのライフタイム管理とリソースの使用を完全に分離できる
コンストラクタでもデストラクタでもリソースの開閉に由来する例外は発生しなくなる デストラクタでたとえば解放忘れの大きなメモリを開放するとしても
その前に他で大きなメモリを確保しようとすると死ぬ
デストラクタでファイルのクローズ忘れをクローズしようとしても
その前に他でファイルを開こうとするとエラーになる
デストラクタでいろいろ開放しても何も助けてない
役に立ったとしても偶然であって実質はバグを握りつぶしてるだけ 今までアンカー売ってないけど>>579向け
デストラクタで何か開放してもバグの温床になるだけ >>580
関係あるからw
同じことをくどくど書くのは嫌いだが、デストラクタの存在理由は
コードの利用者がClose/Disposeを呼び忘れる、というヒューマンエラーに対するフェイルセーフ。
これは議論の余地はないよ みんなフェイルセーフって言葉を使うけど大体意味間違ってる ああ、Dispose呼び出し忘れ対策のデストラクタか
それなら、自分の場合は
・デストラクタには「Dispose(false)」以外書かない(trycatchもしない)
・Dispose()側が例外を投げるかどうかは解放するリソース次第
・デストラクタの中に延々とリソース解放処理なりtry-catchが必要な処理なりを書いてるのだとすれば
そのソースコードは根本的におかしい >>585
だから、デストラクタ「で」積極的にClose処理をするんじゃないの。
Close処理は普通にDispose/Closeに書くに決まっているわけだが、
使用者がそれを呼び忘れても最悪GCのお片付けのタイミングで
Close処理が行われるようにするための仕組みがデストラクタ ごめんもいっこ
・IDisposableなオブジェクトをDisposeせず使用している時点で実装不備とみなしてよい
(フィールド変数だったらポカミスで解放し忘れはあるかもしれないけど、
少なくともローカル変数ならusingを意図的に使ってない時点でコーダーが悪意を持ってると判断する) >>586
いつまで勘違いしてるのか?
フールプルーフとフェイルセーフは別物だからwww >>590
DIに管理させるからusingもDisposeもしないという構成は非常に多い ■ このスレッドは過去ログ倉庫に格納されています