C#, C♯, C#相談室 Part95

■ このスレッドは過去ログ倉庫に格納されています
2017/10/17(火) 00:41:22.60ID:JxIRdCj70
■Visual Studio 2017 Community(無償の統合開発環境)等はこちら
http://www.visualstudio.com/downloads/

■コードを貼る場合はこちら
http://ideone.com/

■前スレ
C#, C♯, C#相談室 Part94
http://mevius.2ch.net/test/read.cgi/tech/1492843013/

■次スレは>>970が建てる事。
建てられない場合は他を指定する事。
VIPQ2_EXTDAT: checked:vvvvv:1000:512:----: EXT was configured
2019/12/08(日) 14:26:41.39ID:90QfBCQ40
さらに設定値を参照してる奴全員に異常値の対応をさせるってありえなくね?
2019/12/08(日) 14:27:36.72ID:7KQ7NXxs0
>>302
その値を保持する
ってのが反映だ
根本から話がずれてる
2019/12/08(日) 14:28:42.21ID:7KQ7NXxs0
>>303
そんな仕様どこに書いてあった?
2019/12/08(日) 14:32:02.79ID:90QfBCQ40
なんかすでに議論に勝つためだけに頑張っちゃってる感じ?
2019/12/08(日) 14:34:19.70ID:rNTMaYhL0
登録ボタンと実行ボタンがある前提で登録ボタンの方は無くせる、と言っているのかな?
2019/12/08(日) 14:41:07.50ID:eGeBS+CxM
>>299
入力中はアンダーラインを引いたりメッセージを出して通知はするが間違ってても即保存する
入力された不正な設定値を読み取る時に無視するあるいは警告を出して無視するはたまたエラーを出して失敗させる
後々設定をアプリ外から弄ることも視野に入れると読み取り時にデータの正確性を保証したほうがいい
2019/12/08(日) 14:50:30.86ID:7KQ7NXxs0
UI→登録ボタンによるチェック処理→設定値保持class
UI→チェック機能を有した設定値保持class
こんだけ
前者はチェック処理で弾けば設定値保持classには異常値が入っていないことが担保できる
後者は設定値保持class自身が正常と判断してるかどうかで異常値があるかどうかを判断する

別に前者の設計が一概にダメとは思わないしこういうこともよくするが後者が詰むという理論は理解できん
2019/12/08(日) 14:51:48.07ID:B7mwO2xN0
>>272
一般的には読みやすくメンテしやすくするため
画面からの入力を処理する役割と設定値を管理する役割は別のクラスに持たせる
ただ簡単なプログラムなら画面クラスに設定値管理の役割を持たせるのでも別に構わない

他クラスから不用意に値を書き換えられないようにするのはそいうふうに設定管理クラスを作ればいいだけ

レス見る限り他のクラスの変数を
プロパティやメソッド経由せずに直接設定したり直接参照してる風に読めるんだが
もしそうなら役割ごとにクラスを分離したのに密結合してるのが一番の問題
でもブチ切れるレベルの人ならササッと書き換えるから心配する必要ないと思う
311デフォルトの名無しさん (ワッチョイ 032d-Do/g)
垢版 |
2019/12/08(日) 15:03:31.77ID:Oblj5J3Y0
>>272
いやいや、2みたいなものは要るし、3は一番ダメだよ
問題なのはフィールドを他クラスのオブジェクトから読み書きする点で、ここをプロパティーやフレームワークの内部コマンドに置き換えたりしないと徐々にコードが酷くなっていくよ
2019/12/08(日) 17:55:31.29ID:zhe6A2K90
この一連の流れは相談か?
2019/12/08(日) 18:19:08.18ID:54HI4DkC0
そうだんですよ川崎さん
314デフォルトの名無しさん (アウアウウー Saa9-FVm2)
垢版 |
2019/12/08(日) 18:25:13.90ID:q5OZjWUaa
正直最初の質問が結局何を質問してるんだか俺にはいまいちよく分からないんだけど、
こんな雲をつかむような話でよくレスが50も進むよねw

まず質問者が何を聞きたいと思ってるのかを明確にするのが先だと思うんだけど
2019/12/08(日) 19:25:44.35ID:h14g0YSH0
>>253の質問内容はわかるだろ
既に>>268, >>270で答え出てるし本人ぽい人も>>284で一応納得してる
レスが伸びてるのは場外乱闘してる基地害が2匹いるっていういつのも流れだからスルーでいい
316デフォルトの名無しさん (アウアウウー Saa9-FVm2)
垢版 |
2019/12/08(日) 19:40:58.07ID:q5OZjWUaa
>>315
漠然とは、ね。
逆にいうと漠然としか分からない

〜だろ?w
頭悪そう
2019/12/08(日) 20:06:20.23ID:h14g0YSH0
いや、わからないならスルーしとけよ
別にお前がわかる必要はないんだしw
2019/12/08(日) 20:19:46.26ID:vQtEDwKW0
また昨日の続きかよ
2019/12/08(日) 20:37:00.33ID:h14g0YSH0
自分がわからないのは質問者のせいだ
って思い込んでる人は一定数いるからw
2019/12/11(水) 18:58:15.46ID:neU6iLAlM
該当クラスがどこのネイムスペースから
なのかすぐわかる方法ってない?
321デフォルトの名無しさん (アウアウウー Saa9-FVm2)
垢版 |
2019/12/11(水) 19:12:17.36ID:A2ve7TTYa
>>320
型名ならマウスオーバーでポップアップ表示されない?
変数ならF12で以下同文
2019/12/11(水) 19:16:20.62ID:neU6iLAlM
>>321
メモ帳しか使えない
すぐわからない?
ideが前提なの?
javaだと省略しないのに
2019/12/11(水) 19:22:09.23ID:3diBwqZu0
名前空間を省略せずに書けばいいだろ
2019/12/11(水) 19:27:51.94ID:2za+15ZK0
javaだってするだろ
2019/12/11(水) 19:31:24.40ID:tBBOlHQ00
>>322
C#に限らず最近の言語はほぼIDEや高機能エディタ前提だと思うが
326デフォルトの名無しさん (アウアウウー Saa9-FVm2)
垢版 |
2019/12/11(水) 20:19:46.44ID:A2ve7TTYa
>>322
ライブラリの型ならC#と一緒にググればすぐ出てくるでしょ
2019/12/11(水) 20:25:15.92ID:EPJ4Sm/w0
vscodeすら入れられないの?
メモ帳縛りとかコンパイルもめんどいやん
てかコンパイラ単体で持ってきたの?
2019/12/11(水) 23:25:24.84ID:fjLZq11N0
昔はviとかで普通にコーディングしてたが
今更メモ帳でコーディングする気にはなれんな
今のIDEとかもう便利すぎる
2019/12/12(木) 00:08:12.86ID:n05Ewb3K0
dotnet buildでいいからコンパイルは楽でしょ
2019/12/12(木) 00:22:15.51ID:AJjh9lU00
今時viだってコーディング支援あるしね
2019/12/21(土) 08:44:14.52ID:mOkYxWI2r
インデントもわざわざ打たなきゃならんでしょメモ帳・・・
2019/12/21(土) 09:28:59.77ID:RVospelqd
>>327
WindowsならC#コンパイラcsc.exeが標準で入ってる。

>>322
でもなあ、IDE無しでは効率悪いでしょ。
規模にもよると思うけどVisualStudio入れられないならC#諦める選択肢もある。
といって代わりに何を使うかで良いのがあるとも思えないけど。
2019/12/21(土) 09:53:05.63ID:elCUYmNmM
クラウドIDE良いよ
インストール不自由でも使える
2019/12/21(土) 11:11:56.97ID:tKqa0Mcd0
vim
https://youtu.be/X0vVVHGFotc?t=306

makeファイルとかの下りは今は不要
2019/12/21(土) 12:14:55.25ID:wj7YAMPY0
メモ帳しか使えない環境だからいくら紹介しても無駄だぞ
2019/12/22(日) 01:12:40.65ID:BLYFt7Uup
最初にメモ帳でC#に特化したエディタ作る
以降はそれで開発
2019/12/22(日) 02:09:51.62ID:thbQEK090
C言語はC言語で書かれてると聞いたことがあるような…
最初にどう始めたかは知らない
アセンブラか他言語で始めてCに移行だとは思うが
2019/12/22(日) 05:49:50.97ID:By9IH60L0
セルフホスティングやな
2019/12/22(日) 12:27:43.38ID:BM7u1zydM
そんなことも知らないのかよ

cの場合は最初にクロスコンパイラを作るから、新しいプラットフォームでもアセンブラは不要。
て、さっきwikiで読んだ
2019/12/22(日) 13:11:54.70ID:0l5I7UXk0
原初の環境では機械語直入力だ
2019/12/22(日) 14:27:23.59ID:4GpMlcpo0
>>339
そのクロスコンパイラとやらはなんの言語で書かれてるんだ?
2019/12/22(日) 15:28:16.06ID:la1jzM750
もちろんCだよ。

gccに関して言えば、まず、Cで書かれた自分自身のサブセットを別のCコンパイラでコンパイルしてから、自分自身のサブセットで自分自身をコンパイルする。

だから今後Cコンパイラがアセンブラで書かれる必要はまったくない。書きたければ書くのは自由だが。

なお、最初のCコンパイラはBで書かれたものとDECマシン向けのアセンブラで書かれたものがあり、Bコンパイラはすべてアセンブラで書かれていた。

僕くらい博識になるとこんなの常識だね。明日には忘れるけど
2019/12/22(日) 15:36:37.89ID:ngCRczT7M
まるでC博士だな
大したやつだ
2019/12/22(日) 15:38:35.28ID:sqLa+RyJa
いきなりネイティブのコンパイラは無理っぽいわ。
2019/12/22(日) 15:47:44.02ID:EAnHyDWL0
>>342
gcc は確か C++ で記述されていたはず、C++ のサブセットなんてどんなものなんですかね?
2019/12/22(日) 16:11:14.32ID:5lkZulIS0
元々はただのCだぞ
2019/12/22(日) 16:23:54.21ID:EAnHyDWL0
>>346
ずいぶん昔に gcc は c++ になってしまいましたよ…
2019/12/22(日) 16:45:16.31ID:lRvby7lea
元々はって日本語わからんのかな
2019/12/22(日) 16:46:38.86ID:uiOI59Hv0
昔のc++はcのコードを一旦出力してcコンパイラでバイナリを作っていたな
2019/12/22(日) 17:21:58.53ID:4GpMlcpo0
>>339
> アセンブラは不要。

と書きながら

>>342
> なお、最初のCコンパイラはBで書かれたものとDECマシン向けのアセンブラで書かれたものがあり、Bコンパイラはすべてアセンブラで書かれていた。

とか自称博識がアホすぎるw
2019/12/22(日) 17:31:31.94ID:EAnHyDWL0
>>348
では質問を変えましょう

その昔の to C トランスレータの頃のC++は、控えめに言って C++98/03 の範囲の何パーセントくらいがカバーできていたのでしょうか?
2019/12/22(日) 18:56:50.05ID:5lkZulIS0
かわいそうに、馬鹿なのだな
2019/12/22(日) 19:39:34.09ID:tqOBQt+/0
>>352
コテでググったら各所で問題児扱いされている奴だったわ
2019/12/22(日) 21:03:00.98ID:0l5I7UXk0
>>350
よーく読んでみ
2019/12/22(日) 21:43:42.23ID:la1jzM750
>>350
バーンドブレードアタッチメントな僕の知識に反論しようとは笑止千万。

前者は今後出てくる新しいPFに関する記述で、後者は当初のコンパイラに関する記述なので、なんの矛盾もない。
2019/12/22(日) 21:55:06.63ID:4GpMlcpo0
>>355
> 前者は今後出てくる新しいPFに関する記述で
誰もそんな話はしてない
Wikipediaレベルのチンケな知識自慢は要らんよw
2019/12/23(月) 00:11:53.87ID:GXjcw1770
だめだこいつ…w
2019/12/23(月) 06:44:48.06ID:AlxEeRKZM
>>357
自己紹介乙ww
2019/12/25(水) 16:59:22.64ID:Zg8ebJFL0
今日もつまらないことで5chは盛り上がっております
2019/12/26(木) 11:49:58.62ID:2UlJm9YS0
using/disposeについて確認したいんだが、
あれって厳密には「リークする」ではなくて、
「解放のタイミングが不明で、場合によっては問題が発生することもあり得る」なだけだよな?
https://docs.microsoft.com/ja-jp/dotnet/standard/garbage-collection/using-objects

具体的にはGDI+オブジェクトのGraphicsやBrush等について、
MSDNのドキュメントもほぼusingなしで記述されているので気になっている。
https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/advanced/how-to-draw-a-line-filled-with-a-texture
一応、using使えということになっていたはずだが?

そこで色々ググって見ると、どうやら以下のようだが、あってるか?
・try-catch で finally にdisposeが入ってなかったとき、(≒つまりusing使わなかったとき)にも、
 例外が発生したその時のリソースも、参照が切れ次第、いつかはGCによって回収される。
・GDI+リソースはシステムリソースで、場合によっては枯渇するから、作法としては不要になり次第解放すべき。
・とはいえ32bit化でこの辺の問題は大幅に緩和され、GDI+はプロセス毎の上限は10,000になってる。
 だから余程酷いことをしない限りこれに引っかかることはない。

結果、作法としては正しいがほぼ命中しない問題に関して一々using使うのもウザイ、
ということでMSDNのドキュメントがusing無しになってる、ということで合ってるかな?
(なお関係ないとは思うが俺が使っているのはVC++/CLIとForms)
2019/12/26(木) 12:35:29.16ID:WMR2NHe80
サンプルプログラムに厳密性を求めるな ってだけ
2019/12/26(木) 12:37:11.96ID:Fsuom43iM
サンプルだから本質には関係ないところをバッサリ省略してるだけでしょ
ガチな例外処理とか入れられても見辛いだけだし
それと同じ話
2019/12/26(木) 13:02:58.04ID:Wx+k6OqqM
まあサンプルをコピペしちゃうレベルなら他にもっとまずいところはいくらでもあるだろうから、
少々Disposeが先延ばしになるくらいは無視しても問題ないかと
2019/12/26(木) 13:36:36.96ID:2UlJm9YS0
>>253
周回遅れだが一応参戦。当該院生が冬休みでもう一度読んでいることを期待する。
他の人も言っているとおり、設計としては253で正しい。直す必要はない。
なおその点はForms->WPFで思想が修正された点であり、(つまりFormsが駄目だった点)
これも他の人が既に言っているとおり、「最新のフレームワークの流儀」で設計するのが妥当。
判断する能力がないなら、とにかく「最新の流儀」に乗っかるのが
無駄に嵌るのを未然に防ぐ適切な方策となるのでそうすべき。

構成としては、おそらく、
「設定値変更画面(V)」「設定値保管用クラス(M)」「他クラス(多分演算ルーチン)(EXE)」で、
これはMVCの通りであり、V-M, M-EXE 間は結合しているがV-EXEは結合していない。
これに対して、誰か(≒老害)に指摘されたのだと思うが、君が253の時点でいいと思っている構成は、
「設定値変更画面(V+M)」「他クラス(多分演算ルーチン)(EXE)」となっており、Mが分離していない。
(=EXE側がVを知っている必要がある)
この構成の利点は、
・コードが多少少なく済む
点であるが、結局使い勝手が悪いので、ずっと改善していくと最終的に253みたくMVCに分離することになる。
2019/12/26(木) 13:37:07.04ID:2UlJm9YS0
>>259
といっても分かりにくいだろうから具体的に指摘すると、
君の問題は、間違った方策で解決しようとして、余計におかしくなっていることだ。
> 他クラスで使用しているときに値を変更されないように2、3を実装したんですけど、単に画面を入力できないようにロックすればよかった。
これは「画面をロック」ではなく、演算開始時に「設定値保管クラスのコピーを演算ルーチンに渡す」とすべき。
これにより、一つの実行画面から多数の演算ルーチンを並列に起動したり、
或いはGUI無しでコマンドラインから起動することも普通に可能となる。
(つまりプログラムとしての汎用性/柔軟性が上がっている)

「クラスのコピー」ってのはディープコピーだが、単純に値が入っているクラスなら、
Cなら構造体の代入、つまり
SomeClass myCopy = reference;
の1行で事足りる。或いは通常、関数呼び出しには構造体への「ポインタ」を用いているはずだが、そこを構造体の「値」に変えればいいだけ。
C#だとstructは値型だったと思うので、設定値保管用『struct』なら自動的に上記が常に行われる構造になるが、
余程小さくない限りそれでは使いにくい筈なので、設定値保管用『クラス』で正しく、何らかの方策でディープコピーをした方がいい。
インミュータブルに組んでいればシャローコピーでも行けるようには出来るはずだが。
2019/12/26(木) 14:38:18.82ID:2UlJm9YS0
>>361-363
つかこれ、どれくらいgraphicsヘビーにすればヒットするんだ?
以下はヒットしているようだが、俺はヒットしない。
https://sorayukinoyume.hatenadiary.org/entry/20121029/1351525436

俺のは40k個Brushを作ってそのまま放置、それを1秒ごとに再描画、
みたいな感じだが、OutOfMemoryなんて起きない。
(ただし、カクつく事があったから今はDisposeを入れてしまったが)
プログラムは演算結果をGUIで表示するもので、演算ヘビーだが、
演算自体はC++ネイティブなのでGCは行われない。
(演算ルーチンではマネージドメモリを消費しない)

なお以下とかは正しいように思う。
https://uchukamen.com/Programming/GC/
https://ladybug.hatenadiary.org/entries/2004/01/10
https://ufcpp.net/study/csharp/rm_gc.html
https://divakk.co.jp/aoyagi/csharp_tips_using.html
https://www.codeproject.com/Articles/48701/Using-GDI-Objects-the-Right-Way
(なお最後はシステムで10,000が上限だと言っているが、これはプロセスの間違いだと思う。《他でそう書いてあったところもあった》
また、タスクマネージャーで見る限り、俺のPCでは全体で10,000は越えているし。
なお一番使っているのはJane2chの8,653だった。Jane糞だなオイ。
chromeは各プロセス毎に600-800位、俺のプログラムはどうやっても50-70を推移してる)

MSも馬鹿じゃないからサンプルコードはそれなりに正しいはず。
絶対にこう書け、なら必ずそう書く。そうでないのはその必要が「普通は」ないからだ。
逆に、普通にサンプルコードで問題が発生するようなら、クレーム来まくりで大変だから、当然のように修正される。
それが為されてないのは、それなりに使用に耐えるコードだからだ。

という感じなのだが、お前らこれヒットするのか?
VC++/CLIとC#だとGC周りがだいぶ違うって事か?
367デフォルトの名無しさん (アウアウウー Sab5-655U)
垢版 |
2019/12/26(木) 14:50:50.75ID:+pzqFzNua
>>366
DC(Graphics)は不要になった時点でDisposeした方がいいと思うけど、
PebとかBrushとかFontとか、このあたりがIDisposable実装してるのは
たぶんWin9xを想定してるんだろうねw

.NET 1.1とかの時代に、Win2kやXPではそこまで神経質にならなくていいよ、
って記事を結構読んだ記憶がある
2019/12/26(木) 14:53:40.92ID:g3TV29VW0
多いから糞って単純な話でもないだろ。表示しているオブジェクトが多いなら仕方がない。
explorerもウィンドウを大量に開くとモリモリ消費する。
2019/12/26(木) 15:25:02.44ID:2UlJm9YS0
>>368
いやJaneはガチでリークしてると思うぜ。

俺のPC内での今の順位
1. Jane2ch 8,677 ←増えてやがるし
2. explorer 1,340
3. chrome 826
以下chromeが20個ほど続く。

字しか表示しねえJaneでどうやって8,677個になるんだよ?
フォントや色でも精々100だろ。
そもそも複数ページ表示してるchrome越えてる時点でだいぶおかしい。
2019/12/26(木) 15:25:33.99ID:2UlJm9YS0
>>367
そのわりにusingガーというのが多いのはなんでだ?
若干Java的オブジェクト指向(オブジェクト指向が唯一絶対神であり、それ以外は認めない)に近い偏見を感じる。
GCなんて手抜きの為の機構であり、逆に言えば、GC使っている以上、書かなくて済む事は書かない、というのが正しいだろ。
全部書け、ならC++を使って全部書き、GCなんて使っている軟派野郎は死ね、とあるべき。

C#でusingって、なんか違うくね?
まあ現実的にヒットするなら致し方ないとして、俺が試した限りでは、どうにもヒットしないように見える。

それとも
> DC(Graphics)は
これはdevice context だけは即時解放した方がいい、ということか?
具体的にはGetHdcメソッドを有する連中だが、見た目Graphicsだけかな。
だとすると俺がやってるBrushでは再現しないのも納得だが、
かといってGraphicsを10,000取得とかいう使い方もないとも思うが。
2019/12/26(木) 15:49:32.19ID:8rtfbEtYp
何をグダグタと気にしてるのかよーわからんな
どうせそのうち回収されるんだから無駄に残ってるのが気にならねえならどうでもいいだろ
精々Janeみたいに過剰に確保されてるのを観測されてクソクソ言われるのが自分のアプリになるだけだ
2019/12/26(木) 16:01:00.94ID:Wx+k6OqqM
つか本来は実際に画面に表示されてる間だけアンマネージリソースを確保すればいいわけで、設計が手抜きなんだよ
まあ、そういう思想でスマートなリソース管理をしてるWPFはゴミのように遅いわけだがw
373デフォルトの名無しさん (アウアウウー Sab5-655U)
垢版 |
2019/12/26(木) 16:08:06.67ID:+pzqFzNua
>>370
なんかちょっと被害妄想激しいよw

IDisposableを実装してたら絶対Disposeすべき、という教条主義を展開してる記事って
あんまり読んだ記憶ないけど、まあusingブロックは十分コンパクトに書けてかつ便利なので、
Disposeしなくてもいい、という確信が持てないなら素直にDisposeするのが普通に安全牌だよね。

※ 個別にDisposeを呼ぶんじゃなくてusingを使え、という趣旨の記事ならいくつか読んだことある
2019/12/26(木) 16:15:52.27ID:2UlJm9YS0
>>371
俺自身は「usingを使うべき」とされる解説ページでお約束的に出される
・そこで例外が発生してdisposeされずに抜けてしまった場合、リークする
が間違い(というか誇大)だと見ているのだが、これが間違ってるかどうかをここで尋ねている。


俺の認識に間違いがないとすると、
俺が試した限りではヒットすることが難しいのに、何故ここまでusingにこだわるのか?というのが疑問になる。
勿論こだわるのもありだが、C#ってそういう言語でもないし。

なお俺のはdisposeしてなくて50-70だぞ。
そこで上記の通り、Brushを40k個作ってもだ。
(もっとも、多すぎてGCが常に速攻行われているだけかもしれないが)

JaneStyleは調べたところOpenJaneからの派生で、OpenJaneはDelphiで、これはGC無しらしい。
つまりモロにリークしてるだけだよ。
375デフォルトの名無しさん (ワッチョイ f12d-vQnI)
垢版 |
2019/12/26(木) 16:30:20.52ID:bzjIw0U90
尋ねてるって言うけど、君の求めてる通りの回答以外は認めないんでしょ
聞くだけ無駄じゃん
2019/12/26(木) 16:40:38.25ID:2UlJm9YS0
>>373
> Disposeしなくてもいい、という確信が持てないなら素直にDisposeするのが普通に安全牌だよね。
つまりこれ。
実はDisposeしなくていいんじゃねえの?というのが俺の疑問。

ヒットしている人がいるから何か要件はあるのだろうけど、俺が試してる限りではヒットさせようがないように見える。
とはいえ、ヒットする可能性がある限り、解説ページ等では「Disposeしなくていい」とは書けない。
だけどほぼ必要がないことはMSも認めてるからサンプルページではusingなんて使っておらず、
usingについてのリンクすらない、というように見える。
(つまりサンプルページを確認しているレベルの奴がヒットさせようがなく、
余計な混乱を防ぐ為にも書かない方がいい、とMSが判断してる。
まあ>>361-363はモロにそう言ってるわけだが)

ただこの状況でも、自分だけが使うならともかく、他人も使うとなると、
using使わないわけには行かない、というのは認める。
だからなんだかなあ、みたいな感じになってる。

結局のところ、これは俺の環境のみならず、
.NETが動くありとあらゆる環境に於いて問題なく動くプログラムを作る為の作法であって、
MSがusing使えと言う以上、書くしかない、ということか。
それが俺のPCでは再現不能だとしても、それはたまたまでしかない、ということであって。
2019/12/26(木) 16:47:16.53ID:BHrZHcGr6
c#のListをイテレーションするサンプルをウェブで探していたんだけど、インデックスでアクセスして回しているコードがよく見つかるんだけど、
Listのデータ構造はリストではないの?
378デフォルトの名無しさん (アウアウウー Sab5-655U)
垢版 |
2019/12/26(木) 16:48:04.03ID:+pzqFzNua
>>376
上に書いたWin9x環境を特に想定した実装、というようなケースを除けば
そのクラスを作ったプログラマは「不要になったらDisposeを呼んで欲しい」と思っているから
IDisposableを実装している。

だからDisposeしなくてもいい、という確信が持てないなら(以下略
2019/12/26(木) 16:55:18.99ID:WMR2NHe80
>>377
「リスト」だとデータ構造が説明できてないと思うのだが
List<T>は配列で実装してるよ
2019/12/26(木) 16:59:42.72ID:F8ujXl8x0
GC任せではなく明示的にメモリを開放していかきゃ動作に支障をきたすような少メモリな環境だって世の中にはある
2019/12/26(木) 17:03:28.05ID:Wx+k6OqqM
>>377
.NETではIListは順序が定義され効率的なランダムアクセスの可能なデータ構造
従って、リンクリストはIListを実装しない
2019/12/26(木) 17:07:04.85ID:2UlJm9YS0
>>378
なるほど確かにその通りだ。

設計者が想定したとおりに使うのが安牌であり、
書いておけば済む物を、特段メリットもないのに書かずに済ませて後で嵌るのは生産性が悪い、というのはC#的には当たりだ。
呼ぶか呼ばないかは使用者が判断するものではなく、設計者がIDisposableを実装するかどうかで示し、それに従え、ということか。

まあ長期的に見てその思想が正しいんだろう。
なるほど納得した。
2019/12/26(木) 17:10:19.42ID:2UlJm9YS0
>>377
https://docs.microsoft.com/ja-jp/dotnet/api/system.collections.generic.linkedlist-1?view=netframework-4.8
2019/12/26(木) 18:35:58.39ID:EoULV8Z50
disposeされなくてもデストラクタで解放されるが、
かなり高コストな処理が発生するそうな

https://ufcpp.net/study/csharp/rm_disposable.html#idisposable
2019/12/26(木) 19:21:56.18ID:2UlJm9YS0
>>384
それは嘘。というか誇大広告。

オブジェクトの寿命が1GC分伸びるだけ。それが深刻になる状況なら、
ファイナライザリストをそもそも作らず、必ずusing/disposeしろ、という設計思想が妥当。…(A)
或いは、ファイナライザリスト内だけ2GC世代分GCするとか、そういうフレームワーク設計も可能。…(B)
いずれにしても、.NETはそうしてない=それは大した問題ではない、とMSが判断している証拠。

といってもGCも進化しつつあるし、この辺もじきに整理されるのかもしれん。
C#8.0のusingはソースコードとしてはほぼ完成型だし、
> using var font1 = new Font("Arial", 10.0f);
> https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/using-statement
型によっては using var でしか宣言出来ない(=静的に確保出来ない=ローカルでしか持てない)ようにすれば、
上記(A)の思想を体現出来る。それが本筋かもね。
形式的にはVC++/CLIのpin_ptrと同じだから、実装する気になればMS的にはすぐだ。
https://docs.microsoft.com/ja-jp/cpp/extensions/pin-ptr-cpp-cli?view=vs-2019
制限はそこに書いてあるが、以下。
> 固定ポインターは、スタックの非静的ローカル変数としてのみ宣言できます。
> 固定ポインターは、以下として使用することはできません。
> 関数パラメーター
> 関数の戻り値の型
> クラスのメンバー
> キャストのターゲット型
「関数パラメータ」に使えない、と書いてあるが、これは言い方が悪くて、
「関数の仮引数の型には使えない」が正しく、実引数として渡す場合はキャストされるので普通に使える。
言葉だと分かりにくいが、
pin_ptr<double> ptr_d;
を void somefunc(double*) に渡すとdouble*に自動的にキャストされるので普通に使える。
これと同様の制限だと、「その関数を抜けた後も保持していて欲しい」オブジェクトには使えないが、
GDI+オブジェクトに関してはこの方向でもコーディングは可能のように思える。
2019/12/26(木) 21:56:25.88ID:Ag2MBuDI0
>>385
> オブジェクトの寿命が1GC分伸びるだけ。それが深刻になる状況

じゅうぶん現実的な状況でなり得るよ。Gen1以上のGCを舐めてる
それが許容できるかは要件次第
ゲームプログラミングでなくとも極力排除すべき要素

そういえば「ガクガクするから結局Dispose呼び出した」とか自分で言ってたね
なんでガクガクしたの?

> 型によっては using var でしか宣言出来ない(=静的に確保出来ない=ローカルでしか持てない)ようにすれば、

論外。ネイティブリソースを持った時点でスタックにしか確保できない型しか作れない言語の出来上がり
ファイナライザを作らずDisposeを強制するというのはそういこと

大した問題じゃないから、ではなく潜在的に負荷を抱える可能性の排除とリソースリークへのセイフティを天秤にかけた結果だよ

> VC++/CLIのpin_ptr

それC#で言うunsafeなfixed相当。関係無い
387デフォルトの名無しさん (ワッチョイ 8b63-b920)
垢版 |
2019/12/26(木) 22:28:04.26ID:9AkEaWNs0
Disposeしないで挙動を調べた結果、問題ないんだったらそのリソースに関してはDisposeしなくていいってことがわかるだけじゃない?
それを一般化してusingなんか使う必要がないのだ/Disposeはファイナライズのときにされるので十分なのだってのはおかしいような。

一々いろんなIDisposableのオブジェクトの挙動を調べてたら検証時間がかかってしょうがないし、
今調べた挙動が将来的にずっと同じである保証もないから、Disposeしてね、と言われているものに関しては、
Disposeされるものだと思って設計変更される可能性がある、と考えて、
問題のないタイミングで行儀よくDisposeしてトラブルの種を潰すってだけの話だと思うんだけど

逆に、使い尽くしてDisposeしなくていいってわかってるんだったら
(例えば自作クラスで、なんかのハンドルを握ったままになったりしないという保証があるなら)
どうぞご自由に、って思うけどね

「自転車ってうちの近くの舗装の綺麗で平坦な道路では手放し運転できるのに、なんでハンドルなんかついてるんだ?いらなくね?」って言ってるようなものだと思うけどね。
2019/12/26(木) 23:04:21.26ID:qz8G02Zg0
なるほど!と読んでたら最後の例えでよくわからんようになった…
2019/12/26(木) 23:08:24.18ID:2UlJm9YS0
>>386
いや多分、みんな求め過ぎなんだよ。
C++erが特にそうだが、C++を何でも出来る言語にしようとしてる。
それと同じく、君もまた、C#を万能言語にしようとしてないか?
つまり、簡単に書け、かつ、最速な言語に、ということだ。

> それが許容できるかは要件次第
俺に言わせれば、ゲームプログラミング等のパフォーマンスクリティカルな状況でC#を使う選択自体が間違ってる。
実際、ゲームは今でもC++が主流で、それはパフォーマンスの問題からだろ。
そういえばUnityはC#だが、(俺はゲーマーでないから詳しくないが)
あれは紙芝居ゲーとかそういう全くパフォーマンスとかどうでもいい系向けではないのか?
グラゴリゴリのゲームをC#で書いて、C++に勝てるとでも思っているのか?

> なんでガクガクしたの?
知らん。ただ、Disposeしてなかったから試しにしてみたらとりあえず直った。
だからGCなのだろうとは思うが、それ以上は確認してない。
ただ、2-3画面毎だったから、Brushで言うと100k毎くらいだ。
2019/12/26(木) 23:09:24.48ID:2UlJm9YS0
> 論外
いやお前の不勉強具合が論外だよ。少なくともRustはそっちを目指している。
もうちょっと単純簡潔な表現のページもあったはずだが見つからないので、グダグダしているが以下。
> 意味論への影響
> スタックアロケーションはRustの言語自体へ影響を与えており、したがって開発者のメンタルモデルにも影響しています。
> Rust言語がどのように自動メモリ管理を取り扱うかは、LIFOセマンティクスに従っています。
> ヒープアロケートされユニークに所有されたボックスのデアロケーションさえも、
> スタックベースのLIFOセマンティクスに従っていることは、この章を通して論じてきたとおりです。
> 非LIFOセマンティクスの柔軟性(すなわち表現能力)は一般的に、
> いつメモリが解放されるべきなのかをコンパイラがコンパイル時に自動的に推論できなくなることを意味するので、
> デアロケーションを制御するために、ときに言語自体の外部に由来するかもしれない、動的なプロトコルに頼らなければなりません。
> (Rc<T> や Arc<T> が使っている参照カウントはその一例です。)
>
> 突き詰めれば、ヒープアロケーションによって増大した表現能力は(例えばガベージコレクタという形の)著しい実行時サポートか、
> (Rustコンパイラが提供していないような検証を必要とする明示的なメモリ管理呼び出しという形の)
> 著しいプログラマの努力のいずれかのコストを引き起こすのです。
> https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/the-stack-and-the-heap.html
と公式は言ってはいるが、Rustの取っつきにくさはここにあって、
要するに既存言語のノリでやったら全然コンパイルが通らないらしい。(俺はやってなから知らんが)
ただし、スタックアロケーションの方が効率も管理も楽なので、スタックアロケーション出来るものはスタックに、という理屈は合ってる。
問題はそれだと柔軟性、つまりデタラメなコーディングが出来なくなる点で、
2019/12/26(木) 23:10:55.58ID:2UlJm9YS0
> 天秤にかけた結果だよ
というのはその通りで、C#は色々なことを天秤にかけて「丁度いい言語」を目指している。
だから、「最速の言語」では今現在ないし、今後ともあり得ないことも自覚してないといけない。
繰り返すが、パフォーマンスクリティカルな状況でC#を使うこと自体が間違いだ。これは今後共だ。


> それC#で言うunsafeなfixed相当。関係無い
確認したが、fixed相当なのはその通り。それで、何故関係ないと言えるのか?
usingで書けるということは、同じ構文のfixedでも書けるということ。
pin_ptrは型なのでグダグダ制限が付いているが、usingやfixedは構文なのでそもそも制限する必要がないだけ。

まあここら辺の理屈はさておき、実際、GDI+リソースをクラスメンバとして持つ必要がどこにある?
例えばGraphicsをControl.CreateGraphicsから生成するのなら、Controlを持っておき、その都度生成することは出来る。
これにより、永続コンテンツ(クラスのメンバ)として持つのは回避出来る。
この制限を付ければ、Graphics自体が「生成されたスコープを抜ければ常に破棄される物」となり、
言い換えれば君の言っているとおり「スタックにしか確保出来ない型」になるが、
usingなんて付けなくてもリソースリークが発生することは原理的になくなるし、
ファイナライザという機構も不要になるので、GC自体も単純化し、高速化する。
とは言ってもここら辺はフレームワーク根幹の設計思想であって、今更グダグダ言っても始まらないが、
Rustで.NETをサポートしたらusingみたいな糞は入らないだろうよ。(原理的に不要)

どの言語スレもそうだが、若干みんな信者になってしまっていて、公平に見れてない。
C#8.0のusingは「書く」前提なら完成型だと思うが、「書かない」方向を目指すことも出来、実際、Rustはそっちを目指してる。
それを糞だと判断するのも自由だが、理解出来ない/知らないのは君の問題だよ。
俺に言わせりゃ、コールグラフなんて抜けるんだから、
usingなんて書かなくとも「このリソースが永続化することはない」というのはコンパイラ側が判断出来ることで、
なら自動的にusing扱いにして、そうじゃないところだけwarning出してくる、というのが理想だと思うが。
2019/12/26(木) 23:23:27.97ID:aYxazJyl0
unityでも3Dゴリゴリのゲームは作るよ
というかスマホで3Dゲームの高クオリティ開発ならunity
1択なくらい。unrealはまだスマホ市場少ない
unityはスマホが多いがコンシューマもPCもそれなりにある
ゲーム以外のARVR分野もかなりunityは多い

言語パフォーマンスより開発パフォーマンスが優先された結果だと思う
だからといって処理速度をないがしろにできるわけじゃない
2019/12/26(木) 23:25:15.01ID:2UlJm9YS0
>>387
いや長期的に見た生産性の為にusingを書いてトラブルの種を潰しておく、というのは納得した。
俺がいくら試しても、俺環境で俺の使い方での結果でしかないから、公式に従った方が得策だ。


ただし言語としてそれが最高か、と言われれば、俺はusingなんて書かなくてもなんとかしとけ、という思想。
つまり、

C#: using書け、ただし、書き忘れても大体何とかなるようには作ってある
Rust: そもそも変数はスタック上にしかアロケートしないので、usingとか原理的に不要
俺: 勝手にコンパイラが色々チェックして、可能なところは自動的にやって、駄目なところだけwarning出してこい

ということ。ただしこれは理想論であって、現実はそうではないのはもう認めてる。
ただそれにしても、「GDI+オブジェクトがスタック上にしか確保出来ない」がそんなに糞だとは思わない。
実際、俺はこれでほぼ組んでいるはずだし。
2019/12/26(木) 23:41:44.91ID:V9vPePAWa
Rustは普通にヒープ使うぞ?
なんか勘違いしてるようだが、そもそもスタックだけで用が足りるんなら所有権だの何だのとRustの高度なリソース管理は要らん
C++のRAIIや、それこそC#で変数をデフォルトでusingにした程度で十分だ
2019/12/26(木) 23:42:14.94ID:2UlJm9YS0
>>392
> 言語パフォーマンスより開発パフォーマンスが優先された結果だと思う
> だからといって処理速度をないがしろにできるわけじゃない
C#の開発パフォーマンスがいいのは認める。
とはいえ、原理的な速度というのはあって、
正直、C++erの「GC使わないけどスマポ使え」ってのはロジック的に間抜け(矛盾してる)と思うが、
Rustの「全部スタック動作と連動」というのは原理的に正しく、逆に言えば、この方法でないとCを越えられない。
だから、根幹の思想は何だかんだで重要で、GDI+に関してはusngではなく「スタック縛り」の方が妥当だったように思う。
ファイルリソースは永続化出来ないとイテレータが使えないのでusingじゃないと無理っぽいが、
GDI+リソースは特に永続化する必然性が無く、大量に生成し、破棄するものだからだ。
パフォーマンス上は断然「スタック縛り」が有利で、
それでコードが書けなくなる/書きづらくなる、ってこともないと思うのだが。

と言ってもMSも気づいているだろうし、当然考えてもいるだろうし、
Rustにも手を出してはいるから必要なら出してくるんだろうけど。
2019/12/26(木) 23:44:51.57ID:2UlJm9YS0
>>394
他言語の「ヒープ」と同等の動作では全くない、ということ。
2019/12/27(金) 01:44:02.82ID:FV6GRoMta
>>396
具体的にどう違うのか説明してね
Rustのメモリ管理は、端的に言えばスマポしか使えない縛りを入れたC++に過ぎないよ
2019/12/27(金) 09:28:31.67ID:9LlS+1cS0
>>393
呼び出しの静的解析だけで、コンパイラ側が自動でusing付けるとか、現状の言語仕様でいけるもんなのかなあ。
行けそうなケースがあるのはわかるけど、すべてのケースで問題なく動作するというエビデンスはなんかある?
あと、俺に言わせりゃ静的解析で出来るだろとのことだけど、設計実装難易度も十分に低いと見積もってて、なんでやらないんだ、と言いたい、ってことなの?個人的には難易度は未知数だと思うんだけどなあ。
2019/12/27(金) 10:30:46.74ID:jG1yqawr0
>>398
参照がスコープ外に持ち出されていないかどうかを判断する必要があるだろうけど、それには
rustのように関数呼び出しに情報を受け渡す拡張が必要になるだろうね。
どうせ文法を拡張するなら、C++/CLIのようにusingより簡単な記述でDispose()の必要性を
判断できるようにする方が現実的かも。
2019/12/27(金) 11:10:40.91ID:AkdF/Ds50
>>398
> 設計実装難易度も十分に低いと見積もってて、なんでやらないんだ、と言いたい、ってことなの?
いや違う。ぶっちゃけ、信者的態度で言われたから言い返してるだけだな。

現実問題として、Rust公式でも述べているとおり、ヒープ+GCの使い勝手は素晴らしく良く、
「コードの書きやすさ」という意味においては現状最高だろう。
だからC#がこれを採用しているのも理に適ってる。

ただし問題は、それを信者的に素晴らしいと君らが捕らえている点で、
これはC#が魔法を使ったわけでもなんでもなく、
単純に、速度を捨てて書きやすさを取っているだけだと正しく認識しろと言っている。
だからパフォーマンスクリティカルだと分かっている状況でC#を使うのが間違いだし、
それはファイナライザが実装されているからGCが1世代分伸びるのも問題だ、というときも該当する。
そこまでのパフォーマンスを求めるときに使う言語ではないし、出来る言語でもない。これは今後共だ。

解決策は既に述べたとおりだが、ここに関してはMSが「間違えた」というのは厳しいが、でも、間違いだとは思う。
usingは「書く」前提ではC#8.0で完成しているが、
問題は、「それが書かなければならない型だ」とユーザーが認識しなければならない点で、
そもそも知らなければ抜けるし、そのためのファイナライザでシステム的に遅いGCになる事を許容しなければならない。
(というほど俺は遅くはならないと思うが、お前らはファイナライザが問題だと言うので)
なら、最初から「スタック縛り」にしてしまえば、SyntaxErrorで落とせるし、GC機構そのものが不要になる。
このときの問題点は多少コーディングの自由が奪われることだが、現実として、
PenやBrushをクラスメンバとして永続させる必要なんて無いし、
GraphicsやFontも生成元『マネージド』情報(既に述べたがControl等)を代わりに持つことによって回避出来る。
結果、馬鹿みたいに「GDI+オブジェクトはその都度生成して、その都度廃棄」なコードになってしまうが、
SyntaxErrorにならなければリソースリークは原理的になくなり、
GCも簡素化/高速化し、using周りの仕様も覚える必要がない、ということになる。
2019/12/27(金) 11:11:26.51ID:AkdF/Ds50
俺が思うC#の利点は、「無駄に覚えなければならない仕様」がほぼ無いことであり、
これは、C++が何でも出来る言語にしようとしている反面、
ほぼ使いもしない仕様を覚える必要がありすぎる状況になっているのと対極的ではある。
ただ、俺に言わせれば、usingも覚えるべき仕様ではない。
「GDI+リソースを持つクラスはスタック上にしか置けません」の仕様だと、何も覚えなくて済み、リーク周りの問題もない。

ただこれは完全に後出しで、MSが間違いを犯したわけではない。
彼等は単純に現状の仕様に乗るようにしてきただけであり、
未来の改訂で「スタック縛り&using廃止」になるのも十分ありうるし、俺はそれを望む。
ただMSはおそらくパフォーマンスよりも書きやすさに振ると思うので、微妙だとは思うが。

> 呼び出しの静的解析だけで、コンパイラ側が自動でusing付けるとか、現状の言語仕様でいけるもんなのかなあ。
要は
Brush xxxxx;
{
// ここで永続化されなければよい
}
なので、中身を辿りきれるかどうかに尽きる。
具体的には、ヒープ上のオブジェクトに保持されているとかが無ければいい。(といってもC#は全部ヒープだが)
解析に問題になるのは関数ポインタを動的に使われるケース(テーブルジャンプ等)だが、
そういうのはほぼやらないから現実的には大半の場合は解析可能だと思う。

> 行けそうなケースがあるのはわかるけど、すべてのケースで問題なく動作するというエビデンスはなんかある?
こんな物はそもそも必要ない。
解析可能なら自動でusing付けろ、解析無理(かつユーザーがusing付けてない)ならwarning出せ、のベストエフォートでいい。
現実的にこれで問題ない。

というかJavaScriptのJITが既にこれに近いことをやっていたはずで、
要は「この関数を抜けたら破棄されると静的に解析済みの変数は最初からスタックに配置する」で、
解析無理なら従来通りヒープに置いてGC、可能な物は纏めてスタックに置いてGC回避で高速化、みたいなことになってたはず。
だから.NETもそれをやればいいだけ。
2019/12/27(金) 11:48:38.34ID:hRCuq6kQM
君が冒している最大の勘違いは、「C#開発者の皆が自分と同じくusingの不便を感じている」という前提を置いていることだ。
実際にはもうFormsの開発なんてC#ではマイナーな部類になりつつあり、
現在の主流であるWeb開発ではDisposeなんか滅多に使わない。
Webのパフォーマンス改善の観点で言えば、(君の愛する)スタックにしか置けない特殊な構造体の導入等により、
C#のGCに極力頼らない高度なメモリ管理は実は一部では既に実現されている。
usingはもはや滅多に使わない機能であり、それほど力を入れて改善されるべき対象ではないんだよ。
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況