C♯相談室 Part30

このエントリーをはてなブックマークに追加
952デフォルトの名無しさん:2006/04/13(木) 06:05:30
関西弁を使う約1名が必死に噛み付いてるのはなぜ?
953デフォルトの名無しさん:2006/04/13(木) 06:54:00
>>948 これから713は713としてかきこんでくれ。おまいが言ってるように。
ほかの人は出来るだけ相手にしないでください。スレ汚されるのが我慢ならん。
954デフォルトの名無しさん:2006/04/13(木) 10:13:31
>>937
ジャギ止まり。
955デフォルトの名無しさん:2006/04/13(木) 12:19:04
いや、ここまでくるとネタだろ
とりあえずスルー推奨
&相手する奴も嵐
956デフォルトの名無しさん:2006/04/13(木) 13:45:34
Hashtableでkeyの値を上書きするのは
Hashtable[key] = 値ですが、
以下の文だと、実行時に
foreachが抜ける辺りで
InvalidOperationExceptionが
発生してしまいます。
ご存じの方、原因をご教示下さい。

//ハッシュテーブルの全ての値をkey値の2倍にする。
 public static Hashtable TestHash()
   {
    Hashtable h = new Hashtable();
    h.Add(1, 0);
    h.Add(2, 0);
    h.Add(3, 0);
    foreach (int i in h.Keys)
    {
     h[i] = i * 2;
    }
    return h;
   }
957デフォルトの名無しさん:2006/04/13(木) 13:50:58
原因は例外メッセージに書いてるとおりだが。
958デフォルトの名無しさん:2006/04/13(木) 14:02:36
foreachの取り出し元の変数に変更加えちゃいけないんだっけか?
そのような処理したい場合はいったん配列にキーコピーとかかしら?
959デフォルトの名無しさん:2006/04/13(木) 14:11:45
つーことでこれでうごいたぽいけど、いい方法かどうかはしらん

Hashtable h = new Hashtable();
h.Add(1, 0);
h.Add(2, 0);
h.Add(3, 0);
int[] a = new int[h.Count];
h.Keys.CopyTo(a, 0);
foreach (int i in a)
{
Console.WriteLine("{0}, {1}", i, h[i]);
h[i] = i * 2;
}
960デフォルトの名無しさん:2006/04/13(木) 14:42:23
>>958-959
ありがとうございます。

foreach のループ対象はkeyの値ですし、
実際に取り出したkey値を操作するのではなく、
ハッシュリストの値の方を編集するわけですし・・・

実際のコードは、以下の様に、編集後のレコードを
もう一つ別に作成したHashtableに入れて、返しています。
キーをコピーした方法も試してみます。
Hashtable h = new Hashtable();
Hashtable rh = new Hashtable();
h.Add("a", 1);
h.Add("b", 2);
h.Add("c", 3);

foreach (string key in h.Keys)
{
  rh.Add(key,(int)h[key] * 2);
}
return rh;
961936:2006/04/13(木) 18:58:33
LVN_ITEMCHANGEDの定義を調べてみたんだが、
こんなのや
#define GVN_SELCHANGED LVN_ITEMCHANGED
こんなの
#define LVN_FIRST ((UINT)-100)
#define LVN_ITEMCHANGED (LVN_FIRST-1)
しか見つからない。
ダメもとでm.Msg == checked((uint)-0x100-1)なんてのも試した。
ローカルの.NET関連のフォルダも見たけどだめ。
WndProcをフォームとリストビューそれぞれに置いてメッセージを調べてみたが、
項目のフォーカスが変更されたときに発行されるものがないような。
それとも>>938は、項目のフォーカスが変更される可能性のある操作を
すべて受け取れって意味だったのかな。
962デフォルトの名無しさん:2006/04/13(木) 19:18:32
あ、そこから解説必要だった?
**N_*** ってメッセージは NotifyMessage って言われるもんで、WM_NOTIFY で親フォームに送られる。
WM_NOTIFY を受け取った場合、LPARAM を NMHDR 構造体にキャストして code メンバでどのメッセージなのか確認する。
// これに関しては unsafe でポインタ使った方が凄い楽。
で、pnmhdr->code == LVN_ITEMCHANGED のときにあれこれする。
ちなみに、WM_NOTIFY は親フォームに流れるけど、
.NET では親フォームはそのコントロール自身にも (WM_REFLECT + WM_NOTIFY) を改めて送信するので、
コントロール自身でも判断可能だ。
963デフォルトの名無しさん:2006/04/13(木) 23:16:30
713の降臨まだぁ?
964713:2006/04/14(金) 00:12:53
今APIについて猛勉強中
資料が少ないから大変だけど、おもしろいねこれ
てか、選ぶ言語間違えたかな。C++のほうがいいみたい
965704:2006/04/14(金) 00:32:40
>>705
うーん、以下のコードだと呼ばれないんですが。
適当なFormの中のコードです。
Formに配置されたボタンを押すとgcButton_Clickが呼ばれると思ってください。

private Button testButton = null;
private void gcButton_Click(object sender, EventArgs e) {
 if (testButton == null) {
  testButton = new Button();
  testButton.Disposed += new EventHandler(testButton_Disposed);
  Controls.Add(testButton);
 } else {
  Controls.Remove(testButton);
  testButton = null;
  GC.Collect(); //<- ここでGCしてもtestButton_Disposed()が呼ばれない
 }
}
void testButton_Disposed(object sender, EventArgs e) {
 Debug.WriteLine("button disposed.");
}
966デフォルトの名無しさん:2006/04/14(金) 00:37:14
GC.Collect() したら GC されるって保障されてんだっけ?
967デフォルトの名無しさん:2006/04/14(金) 00:50:32
うっわぁ、ほんとに713降臨しやがった^^;
君うざすぎw
C++の方がいいって思うんだったらC++に乗り換えなよ
そんでもうC#には関わらないで^^





っていうと、今更乗り換えられないとか、途中で投げ出したくないとか、C#をちゃんと覚えてからとか言うんだろうね
そんでここのスレにいつまでもまとわりつくと。
968デフォルトの名無しさん:2006/04/14(金) 00:51:49
1回目はファイナライズキューに入り次のGCで破棄される
969デフォルトの名無しさん:2006/04/14(金) 01:00:33
>>965
いわゆるデストラクタってのはファイナライザのこと。
ファイナライザはオブジェクトが削除されるときに呼び出される。
で、Disposed イベントは Dispose() メソッドが呼ばれたときに発生する。
Dispose() とファイナライザは直接は関係ないよ。
Disposed を発生させたいなら明示的に Dispose() を呼び出さないと。
970デフォルトの名無しさん:2006/04/14(金) 01:04:20
っていうかぁ、ファイナライズではイベントハンドラなんて呼ばれないと思うんですけどぉ。
971デフォルトの名無しさん:2006/04/14(金) 01:05:54
あう、時間差で…
>>970>>965あてなの
972704:2006/04/14(金) 01:16:18
>>970
じゃあ>>391は嘘なのかな?
IDisposeを実装してるオブジェクトはDispose()はプログラムで明示的に呼び出せと?
ちなみにボタンを動的にControls.Add()したままの状態でFormを閉じるとDisposeが呼ばれます。
973デフォルトの名無しさん:2006/04/14(金) 01:16:53
確かデストラクタはFinalizeメソッドに変換されるんだよな。

IDisposable実装クラスのファイナライザは、通常Dispose(false)を呼び出すように設計しなければならない。
んで、実際System.Windows.Forms.Buttonクラスの基本クラスであるSystem.ComponentModel.ComponentクラスのFinalizeの中身を
覗いてみると、ちゃんとDispose(false)を呼び出している。
ちなみにDispose(bool disposing)メソッドの中でイベントもちゃんと呼ぶようになってるぞ。
だからGCがButtonクラスの回収をすればイベントは発生するはずということ。

んで、GC.Collectっていうのはガベージコレクタを即実行するわけだが、
ガベージコレクタってのは世代管理を行っていて引数を指定しないでGC.Collectを呼び出した場合は
メモリがやばくない限り1世代目の回収しかしない(あとここで世代移動が行われる気がした)。だから必ずしもButtonオブジェクトがGCに回収されるとは限らないわけだ。

つまり、GC.Collect(3)ってやればOKだと思う。
974デフォルトの名無しさん:2006/04/14(金) 01:22:32
もしかしたら多少違ってるかもしれんから、一度自分でGCについてちゃんと調べることをお勧めしとくよ。
975デフォルトの名無しさん:2006/04/14(金) 01:22:56
>>972
なんで嘘になるのさ。
Disposed イベントなんて所詮ただのイベント。オブジェクトの掃除とは何の関係もない。
IDisposable は Dispose() が呼ばれなかったら最終的にファイナライザが Dispose(false) を呼び出す。
Dispose(false) は Disposed を発生させないってだけの話。

>>973
Dispose(false) の場合は Disposed を発生させない。
ファイナライザでは参照型のメンバにアクセスしちゃ駄目だから。
もちろんイベントの実体もデリゲートインスタンスなのでファイナライザではさわれない。
さらに、GC.Collect() は全世代のオブジェクトに対して GC を行うとリファレンスに明記されてる。
976デフォルトの名無しさん:2006/04/14(金) 01:26:23
>>975
すまん、至る所で勘違いが混じってたな。首吊ってくるorz
977970:2006/04/14(金) 01:27:38
>>972に突っ込もうと思ったけど>>975がみんな書いてくれた…
978704:2006/04/14(金) 01:31:07
>>975
理解しました!
動的ボタンを直接Buttonクラスを使わず以下のように継承してMyButtonを定義し、
overrideしたDisposeメソッドはきちんと呼ばれました。
 private class MyButton : Button {
  protected override void Dispose(bool disposing) {
   Debug.WriteLine("button disposed." + disposing);
   base.Dispose(disposing);
  }
 }
MyButton testButton = null;
979デフォルトの名無しさん:2006/04/14(金) 01:32:42
>覗いてみると、ちゃんとDispose(false)を呼び出している。
>ちなみにDispose(bool disposing)メソッドの中でイベントもちゃんと呼ぶようになってるぞ。
ここまで見といてなんでその際の条件を見ないw
980デフォルトの名無しさん:2006/04/14(金) 10:07:42
GC.WaitForPendingFinalizersも呼んでおくと幸せになれそう。
とチラシの裏。
981デフォルトの名無しさん:2006/04/14(金) 23:20:39
>>962
丁寧な解説どうもありがとう。
LVN_ITEMCHANGEDの定義の
#define LVN_FIRST (0U-100U)
#define LVN_ITEMCHANGED (LVN_FIRST-1)
が0xffffff9bなんだろうということもやっとわかった。
ただ、LVN_ITEMCHANGEDどころかまずWM_NOTIFYが送られてこないような。
if( m.Msg == 0x004e ){ ... } //こんな感じでスタンバってる
フォーカス移動を知りたいだけなのになんでunsafeとか使わにゃいかんのだ、Gates。
982デフォルトの名無しさん:2006/04/14(金) 23:29:05
>GC.WaitForPendingFinalizersも呼んでおくと幸せになれそう。
なんですと?
983デフォルトの名無しさん:2006/04/14(金) 23:56:37
>>981
WM_NOTIFY は親フォームに送られるって点は OK ? コントロール自身が待ってない?
ていうかここにかいてあった
ttp://hongliang.seesaa.net/article/16550502.html
984デフォルトの名無しさん:2006/04/15(土) 00:19:03
MSのコードは適当なタイミングでGC.Collectとか
GC.WaitForPendingFinalizersとか呼んでるね
985デフォルトの名無しさん:2006/04/15(土) 01:23:26
968が正解
986デフォルトの名無しさん:2006/04/15(土) 12:28:54
MenuStripを持つ子ウインドウをそのメニューから
this.Close()で閉じるとObjectDisposedExceptionが発生するんですが
ただしい娘ウインドウの終了の仕方ってどんなんでしょう?
987986:2006/04/15(土) 12:42:30
いまテストしてみたんですが、

ToolStripMenuItemの
DropDownItemClickedイベントでthis.Close()で閉じると例外、

サブメニューそのもののClickイベントで閉じれば例外が起きません。
こっちでやれってことですかね
988デフォルトの名無しさん:2006/04/15(土) 12:42:48
微妙に意味が取りづらいが、発生しないよ?
989986:2006/04/15(土) 13:06:54
えーとですね、
子フォームにMenuStripをくっつけて、最初のアイテムを"ファイル”として、
そのサブアイテムを”閉じる”とします。

”ファイル”のDropDownItemClickedでthis.Close();を呼ぶと例外、
"閉じる"のClickでthis.Close()なら普通に閉じる。

うちでは100%再現するんですが、(VS2005Express)
とりあえず下の方法でお茶を濁しました……
990デフォルトの名無しさん:2006/04/15(土) 13:10:04
>>989 自分はそういう自分のせいでない(と思いたい)例外が出るときは、めんどくさいのでイレギュラーな手でお茶を濁す。まぁ全体に影響しない範囲でだが。
この場合なら別スレッドにhandleわたしてPostMessageすると思う。
991デフォルトの名無しさん:2006/04/15(土) 13:10:26
いや、それは当然だろ。
さあサブメニューを表示しようって時にいきなり親が Dispose されるんだから。
なんで DropDownItemClicked で this.Close なんだよ。
992デフォルトの名無しさん:2006/04/15(土) 13:16:22
>>991
ああ、そういうことですか。

"DropDownした先のItemをClicked"じゃなくて
"DropDownするItemをClicked"って意味だったんですか。

あんまり腑に落ちませんが
ありがとうございました。
993デフォルトの名無しさん:2006/04/15(土) 13:27:09
うお、1000ギリギリでも埋めに入らねぇ。
994デフォルトの名無しさん:2006/04/15(土) 13:30:56
つか新スレ立ててくれ新スレ。私は無理だったし。
スレタイの♯は半角だと消えるから全角でな。Shift+3 は別の文字だから「しゃーぷ」を変換するんだ。
ていうかコピーすればいいな。
995デフォルトの名無しさん:2006/04/15(土) 13:32:10
んじゃ建てるよ?
996デフォルトの名無しさん:2006/04/15(土) 13:34:53
997デフォルトの名無しさん:2006/04/15(土) 13:39:36
ksk
998デフォルトの名無しさん:2006/04/15(土) 13:40:12
乙&梅
999デフォルトの名無しさん:2006/04/15(土) 13:41:12
Vistaはよせい
1000デフォルトの名無しさん:2006/04/15(土) 13:43:06




          次スレ以降、>>713は書き込み禁止
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。