c#デリゲート関連の命名について

このQ&Aのポイント
  • c#デリゲート関連の命名についての質問です。SampleDelegateとSampleActionにはどのような名前をつければいいのか悩んでいます。
  • SampleDelegateは値を取得するメソッドを表すので、'~すること'を表す動名詞を使用するのが適切です。SampleActionも同様に、値を取得することを表す名前にするとよいでしょう。
  • 例えばSampleDelegateは'GetValue'、SampleActionは'ValueGetter'という名前を使うことができます。しかし、最終的な命名はコードの読みやすさや一貫性を保つことが重要です。
回答を見る
  • ベストアンサー

c# デリゲート関連の命名について

 こんにちは。c#初心者です。  今回はデリゲート関連の命名についての質問です。 // ――――――――――――――――――――――――――――――― // 簡素化のため、フィールド変数のまま書いています public delegate int SampleDelegate(); public SampleDelegate SampleAction; public int Value {   get { return SampleAction(); } } // ―――――――――――――――――――――――――――――――  上記のようなコードを書いているのですが、「SampleDelegate」に当たる部分、「SampleAction」にあたる部分にはどのような名前をつければいいのかと迷っています。  SampleDelegateは値を取得するメソッドを表すので「GettingValue」や、「ValueGetter」がいいのか、それとも「ValuePasser」みたいなのがいいのか、それ以外がいいのか、  SampleActionも「ValueGetter」がいいのかそれとも、メソッドと同じように「GetValue」にするのがいいのかそれ以外がいいのかと悩んでいます。  最初は「SampleDelegate」が「GettingValue」、「SampleAction」が「ValueGetter」になっているのですが、反対の方がいいような気がしたり、その他いろいろで困っています。  どなたか詳しい方いらっしゃいましたら教えていただけませんか? できれば「『SampleAction』は動作自体だからGettingValueのように『~すること』 のように動名詞を使い方がいい」のように他の命名においても応用が利く教え方にしていただけるとありがたいです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.27

>結局、setとAddは結局同じ動作を含んでいたことに気づいて~ >何もデリゲートを使わなくてもやりたかったことの一部が出来たんです。 はい、そういう事ですね。 >_sampleAction( ←ここまで入れるとツールチップで変数名が表示されるので 或いはカーソルをかざしたりしても出てきますね。 こういうのをひっくるめてインテリセンス(Intellisense)というんですが VC++2008ではこいつがC#に比べてかなり貧弱なんですよw ずっと前にVC++で同じようなことしようと試みた事があるんですが、結局その時は どうあがいても、カーソルをかざすのか、キー入力だったかの、どっちか片方だけしか反映できないという結果だったように思いました。 (まぁ、「貧弱」というのはそれだけの理由では決してありませんが) 次のバージョンでは強化されたと小耳にはさんだので(もうさらにその次が既に触れられるのかな?)幾分期待はしていますが。 ・<>について たぶん見つかりました。 コレっぽい感じではないですか? http://d.hatena.ne.jp/saiya_moebius/20090129/1233243475 html上でのあれとおんなじみたいですね &lt; と &gt; 使えば出来るっぽい感じです List<T> ↓ List&lt;T&gt; で、リンク先の方はこれだと書いてる側は分かり辛いってんで {}をかわりに使ってらっしゃる提案をされてますが それから、<include>使って別ファイルに置き変え出来るっぽいですね http://msdn.microsoft.com/ja-jp/library/9h8dy30z.aspx これを使えば、日英別々にxml作っといて、後で簡単に切り替えるといったことが出来るかもしれません。 私のとこでは dllにビルドしといて 別のC#アセンブリから 参照設定して(xmlファイルも運んどいて)呼び出したら 表示出来ました が 自分自身のアセンブリのとこに /// <include file='xml_include_tag.doc' path='MyDocs/MyMembers[@name="test"]/*' /> とかをやっただけでは出ず。 うーむ これが自分のとこでも反応してくれれば最強なんですが これは出来ないのかな?

koumei000
質問者

お礼

 ありがとうございます。おかげさまで大助かりです。  インテリセンスってオートコンプリートの事だけかと思っていました。あのツールチップもそうだったのですね。c#に慣れてきてたころに一度VC2010Expressに挑戦してみたのですが、「this->」の時点で意味が分からなくなった上、全然インテリセンスが表示されないのでいったん諦めて、しばらくはc#一本に絞ることにした覚えがあります。  「<include>」、覚えておきます。  初心者の長い質問に付き合ってくださって、ありがとうございました。

その他の回答 (26)

回答No.26

あ、そかそか <summary>などなどを使えば C#では解説が出るんでしたねw VC++2008だとインテリセンスに頼れないことが多々あるので、すっかり忘れていました。 このへんのことは既にOKってことですかね? http://ufcpp.net/study/csharp/st_comment.html 仮に 言語について一つだけ表示したい場合は とりあえず開発中は解説が見えなくてもいい! と割り切れるなら、適当に「かぶりそうにない文字を割り当てといて」 後でそいつらを置換するという方法は思いつきますが…

回答No.25

>VerifiedListについて そうですね 一個で済むところなら一個ですました方が断然いいです。 また privateかつreadonlyであるのなら、使用箇所で引数として取るという方法でなくとも、フィールドとして持ってしまっても全体像の可視性は全然よくなってると思います。 >それと後、XMLのコメントのところに「 // 」で区切って日英の両方を書いているのですが、こんな書き方はしないほうが良いのでしょうか?(場合によって<para></para>も使います) それは分かりません。使う人が「こういう風に使う」という仕様書だけ見れば、あとはコード直接見えなくても使えるぐらいなのが、良質なライブラリと言えるので 別途ドキュメント化してしまう方が一般的かもしれません。 ただ、オープンソースにして誰でも改良を施せるようにするなら こういう形式でもいいかもしれません。 その場合は、あとは何らかの テキストエディタ(ソフト)かなんかで、文字の置き換えを簡単に行ってくれるような機能がもしあれば、(無駄ないソースで)日本語用・英語用に別々にリリースするのも可能かもしれません。 >あと、XMLコメントないで「<」の記入に苦労しており、苦しみ紛れに環境依存文字「˂」「˃」で代用していますが、あまり良くないと思います。<xmp></xmp>のようなタグは無いでしょうか? それとも「(in T)」などで代用したほうかよろしいでしょうか? うーん、コメントに関しては全然詳しくないですw 申し訳ない 私はコメントよりソース主義的なところがあって 人のコードを読む時も 1.まずコメントをほとんど読まずに消す 2.自分の読みやすい文法に書き変えながらついでに挙動を追っていく 3.一通り整形し、目を通して尚且つぱっと見で意味が分かり辛い部分があったら、そこではじめて、消した部分に相当する元のソースのコメントを読んでみる という手順を、ほとんど踏むのでw 何しろコメントは間違ったこと書いてても、それを修正するの忘れてても コンパイルエラーにはなりませんからね。 とはいえ、上記のとおり、「オープンソース」かつ「概要説明毎回あり」のケースであれば考えた方が良いかもしれませんが どういうものをどう書きたいところを 今はその部分が<>含め、どうなっているかっていう具体的なところが分かれば、調べられる、かもしれません。

koumei000
質問者

お礼

 回答ありがとうございます。  結局、setとAddは結局同じ動作を含んでいたことに気づいて、Clear、Removeは操作ミスで呼び出されるとしたらユーザーだということに気づきました(それ以外は普通、バグって言いますよね)。  あと、よく考えてみれば何もデリゲートを使わなくてもやりたかったことの一部が出来たんです。 > どういうものをどう書きたいところを今はその部分が<>含め、どうなっているかっていう具体的なところが分かれば、調べられる、かもしれません。  今回のように自前でデリゲートの型を用意した場合、 _sampleAction( ←ここまで入れるとツールチップで変数名が表示されるので 便利なのですが、その変数にラムダ式を代入する場合に引数の型や名前が思い出せず、しぶしぶどこかで上記のよう入力してにツールチップに頼ったりしていたので、それならいっそのこと /// <summary> ///   説明 ///   <para>>>> void Method(int value, List<T> list)</para></summary> private Action<T> _sampleAction; のようにしようと決めたのです…が、なんと、上記の場合「<」がタグ開始として認識されてしまう ということで「˂」「˃」を代用していました(ツールチップ内では「<」「>」より「˂」「˃」の方が違和感が少なかったので使用していますが、「<」「>」でもいいような気がしてきました)。

回答No.24

もうちょい補足です >>Class1はそれを真似たのですが、よくなかったということですか。 >そいつは状況次第ですね。Class1はあくまでユーザー定義の自由なクラスという仮定ならば、ということですが ユーザー定義の自由なクラスでなくても、「設定、取得するものは一種類しかない、配列やリストのような働きをするクラス」や「ハッシュっぽいもの」ならば全く問題ないし むしろ分かりやすいかと思います。

回答No.23

まぁ、ここまでしっかりと受け答えをされていらっしゃる ということで「初心者」と自称されていますが 仮に自身でそう定義したとしても、客観的には「そんじょそこらの一般的な初心者」とは5枚も6枚も違うと思います。 ・分からないことがあったらどんどん聞く、或いは調べる ・自分に分かる範囲で、十分調べている こういう人は言語に限らず伸びるんですよ。頑張ってください。 で、本題ですが >Class1はそれを真似たのですが、よくなかったということですか。 そいつは状況次第ですね。Class1はあくまでユーザー定義の自由なクラスという仮定ならば、ということですが >不正な削除・クリア対策または他のインスタンスとの連携ができないかと それをチェックするデリゲートを送るとしても 結局監視側はそれを知ってるってことになるでしょうから その部分でだけ引数で送る、という手ももちろんあります。 (インスタンスを作って渡さないといけないとなると、大規模開発ではその下準備が後で「どうだったっけ」となりやすいので、使用箇所で引数で送った方が、概して分かりやすいという意味です。) >結局不正な値、インスタンスの追加をまたは、不正な削除を許すことになります。 はい、その「アホ操作」の可能性を全て先読みしてライブラリ側が潰すのは大変な作業ですし、実行時に無駄な処理が発生してしまう恐れも非常に大きいので 「アホ操作」自体が発生しにくいように 「分かりやすい操作」になっている方がいい、っていうのが普通の考え方です。 >例えば、引数「text」が「"word"」という~ これはおそらく、私が最初の方で書いた >文字列長判定や開始、終了の文字、特定の文字(列)が、ある文字列中に含まれているかの判別については >Listの管理とは概念的に別なので~ に該当すると思います。 例えば >var ages = new int[loop] { 5, 4, 3, 2, 1, 0, -1 , 2, 3, 4 }; >// i = 6のとき例外が発生。 >for ( int i = 0; i < loop; i++ ) > sample.Ages.Add(ages[i]; >} こんな感じの事を、下記LimitableListを使用してやってみましょう。 //ユーザー定義の自由なクラス internal sealed class MyAgeList { //今回は要素の上限数使ってないのでList<int>でも別にOK LimitableList<int> _list; //ageが利用可能な値かどうか。privateで問題ない。 bool IsAvailableAge(int age_) { return 0 <= age_ && age_ <= 200; } public int this[int i]{ get { return _list[i]; } set { if (!IsAvailableAge(value)) throw new ArgumentOutOfRangeException("item"); _list[i] = value; } } public bool Add(int age){ return IsAvailableAge(age) ? _list.Add(age) : false; } public MyAgeList(){ _list = new LimitableList<int>(); } } 込み入った初期化もなく、ものすごく単純ですよね? ↓使ってみる。 MyAgeList agelist = new MyAgeList(); int[] ages = new int[] { 5, 4, 3, 2, 1, 0, -1, 2, 3, 4, 202 }; foreach (int i in ages) { if ( !agelist.Add(i) ) Text += " " + i; } 結果(追加できなかった要素を表示する) -1 202 いかがでしょう?

koumei000
質問者

お礼

 ご意見ありがとうございます。 > こういう人は言語に限らず伸びるんですよ。頑張ってください。  はい。ありがとうございます。でも、やっぱり独学では井の中の蛙になってしまうのでこの度は本当に感謝しています。  よくよく考えたのですが、少々凝りすぎていたのかもしれません。そこで間を取って、 /// <summary> ///   値のチェックをサポートしたリストを表します ///   // Represents a list of objects ///   that can check validness of value.</summary> /// <typeparam name="T"> ///   値の型 ///   // The type of value</typeparam> public class VerifiedList<T> {   public delegate bool ValidnessCheckCallback(T value);   // こいつで、追加、割り当て時にチェックする   private readonly ValidnessCheckCallback _validnessChecker;   public VerifiedList(ValidnessCheckCallback validnessChecker, …)   {   ……   } }  こんなのはいかがでしょうか? 自分なりには改善できたつもりなのですが。  それと後、XMLのコメントのところに「 // 」で区切って日英の両方を書いているのですが、こんな書き方はしないほうが良いのでしょうか?(場合によって<para></para>も使います)  あと、XMLコメントないで「<」の記入に苦労しており、苦しみ紛れに環境依存文字「˂」「˃」で代用していますが、あまり良くないと思います。<xmp></xmp>のようなタグは無いでしょうか? それとも「(in T)」などで代用したほうかよろしいでしょうか?

回答No.22

文字列長判定や開始、終了の文字、特定の文字(列)が、ある文字列中に含まれているかの判別については Listの管理とは概念的に別なので Listサイドに突っ込まれてない形になってる方が分かりやすいです。 (Listから取り出した文字列を使って、Listの外で判定する) ここもまた、オブジェクト指向の考え方です。 「Listの要素に」含まれているかどうかの判別は List<T>を継承してればExistsで簡単にできると思いますが もっと簡単にするならこういう事も考えられます ↓(制限可能、という意味でLimitableに変え、さらに0のときの仕様を変えました) public class LimitableList<T>: List<T> { //さっきのは実際には「0より大きい時」でしたが、今回はほんとに0以上を指定すると上限を設定 public int Limit { get; set; } public new bool Add(T t) { if (0 <= Limit && Limit <= Count) return false; base.Add(t); return true; } public void Unlimit(){ Limit = -1; } public bool Exist(T t){ return Exists(a => { return a.Equals(t); }); } public LimitableList(int limit) { Limit = limit; } public LimitableList() : this(-1) { } } 実験 using NameOfLibrary; ・ ・ ・ LimitableList<string> list = new LimitableList<string>(0); Text += " " + list.Add("追加0"); //この時点では追加されない list.Unlimit(); Text += " " + list.Add("追加1"); Text += " " + list.Add("last"); Text += " " + (list.Exist("last") ? "exists" : "not exist"); Text += " " + (list.Exist("追加0") ? "exists" : "not exist"); 結果 False True True exists not exist

koumei000
質問者

お礼

 ご指摘ありがとうございます 「TreeListView」は「TreeView」の間違いでした。 > Get~というメソッドを「~」の部分を変えて2つ作るほうが、普通な可能性があります。  TreeViewに「public ControlCollection Controls」や、「public TreeNodeCollection Nodes」などがあり、それぞれのコレクションにインデクサ、Add、RemoveメソッドがあったのでClass1はそれを真似たのですが、よくなかったということですか。 > ほとんどprivateやprotectedで作っています。(なので使う側としてはごちゃごちゃしてません)  CListは基本的に他のライブラリ内のクラスのパーツになります(その際ごく一部は派生して使用)。使う側は基本的にインデクサと、Add系とRemove系とClearだけです。 > ということであれば、先ほどの私のLimitListをprivateフィールドにもった もうちょっと具体的なクラスをまた作ればいい  不正な削除・クリア対策または他のインスタンスとの連携ができないかと > (Listから取り出した文字列を使って、Listの外で判定する)   この方法は最初に思いつきましたが、結局不正な値、インスタンスの追加をまたは、不正な削除を許すことになります。 > 「Listの要素に」含まれているかどうかの判別は  勘違いを引き起こさせてしまったようです。例えば、引数「text」が「"word"」という文字列を含んでいるかどうかと言う意味です。含んでいなければ例えば文法エラー扱いにするなど。  よく考えてみれば名前が微妙だったかもしれません。「~List」より「WatchedCollection」、「~Collection」のほうが良かったのかもしれません。

回答No.21

> LimListを例えばClass1内部で宣言し、取得専用publicプロパティ「public LimList<int> Ages { get; set; }」として使ったとします。その際、外部、例えばClass2から「Ages.Limit」を勝手にいじられたのではいくらClass1で制限を調整しようと思っても無理です。 その前提は、そもそも「オブジェクト指向的には非常事態」です。 そういうときは普通はLimList<int>をpublicにアクセスできるようにしたりしません。 Class1がどういうクラスであれ、例えば そいつに対して Add何々(~); というメソッド「だけ」を公開し そのAddの内部で_agesとかへの追加処理を施す、といった形にします。 >LimListを2つ以上使うような場合では無理ですし、何を取得するのかが明確でない場合も多いと思います。 そういうときはClass1に Get~というメソッドを「~」の部分を変えて2つ作るほうが、普通な可能性があります。 TreeListViewのNodesプロパティがあるとしたら こいつをpublicにするかどうかはまた別問題です。 私がC++で作ったものは、最終的に操作名が分かるstaticな関数名以外 ほとんどprivateやprotectedで作っています。(なので使う側としてはごちゃごちゃしてません) >宣言場所のみ、または許可された範囲内でのみ制限や処理をいじれるようにするため ということであれば、先ほどの私のLimitListをprivateフィールドにもった もうちょっと具体的なクラスをまた作ればいい、あるいはもしLimitがreadonlyに出来るならそれで十分、というだけです。

回答No.20

編集途中でした。 LimitedList→LimitListに直してください。

回答No.19

そういうことであれば、もっともっとシンプルにするべきだと思います。 CList(Controled)と言われても、聞くまでControledの意図が正確に分かんなかったのと、Controledという意図を読み取ることを、聞くまで半ば放棄してしまいかねないこと…(ClassなのかControlなのか、その他なのか) なにしろ、C++だとCListという名前のものがMFCというライブラリにあるなどなどから CListという名前から「そういう意図が読み取れる」という事は期待しない方が良いように思います。 この場合名前から読み取らなくても使えるくらい簡潔になっているべきと思います。 また、現状ではCListActionBox<int>やCList<int>の制御コードを、使う側がいちいち書かないといけないということになりますが こういったことは汎用ライブラリらしくありません。 CList<int>とCListActionBox<int>の関係性を理解してないといけないというのもきついとこです こういう意図なら 少なくともデフォルトでは、CListがそれをユーザーに変わって自動で行うような機構にするのが自然です。 このコードだと現状LimitList、かSafeListぐらいの意味合いにして そう言うListにしてしまった方が分かりやすいと思います。 Listに機能追加するという事なら 細かいとこは省きますが using System.Collections.Generic; [assembly: CLSCompliantAttribute(true)] namespace NameOfLibrary { public class LimitedList<T>: List<T> { public int Limit { get; set; } //0以上を指定すると上限を設定 public new bool Add(T t) { if (0 < Limit && Limit <= Count) return false; base.Add(t); return true; } public LimitedList(int limit) { Limit = limit; } public LimitedList() : this(0) {} } } この程度でも、意味的にはそこそこ行ける(ちゃんとやるならListの機能をしっかり把握しきるか、それに依存しないように自分で0から書かないといけませんが) と思います。 色々実験↓ NameOfLibrary.LimitList<string> list = new NameOfLibrary.LimitList<string>(); Text = ""; Text += " " + list.Add("a"); Text += " " + list.Add("list[1]"); Text += " " + list.Add("last"); try { list[0] = "Nice to meet you."; list[3] = "3333"; } catch (ArgumentOutOfRangeException e) { Text += " " + e.Message; } Text += " " + list.Count; list.ForEach(s => { Text += " " + s; }); 結果(実際は改行ではないですが、分かりにくいので改行します) True True True インデックスが…(ArgumentOutOfRangeException例外) Nice to meet you. list[1] last

koumei000
質問者

お礼

 ご指摘ありがとうございます。  実はLimList<T>(Limited List)は製作済みです。ただし、これはIComparable<T>を実装したものしか対応しておりません。そこで文字列であろうと、Collorであろうと対応できるもので、なおかつ特定の値や動作に対して反応し、カウントするなどの機能をもたせるためのものでもあります。  さらに、~ActionBoxを作ったのは訳があります。    LimListを例えばClass1内部で宣言し、取得専用publicプロパティ「public LimList<int> Ages { get; set; }」として使ったとします。その際、外部、例えばClass2から「Ages.Limit」を勝手にいじられたのではいくらClass1で制限を調整しようと思っても無理です。  Class1で「public int this[int index] { get; set; }」のようにする手も有りますが、LimListを2つ以上使うような場合では無理ですし、何を取得するのかが明確でない場合も多いと思います。実際、例えば「TreeListView」は「Nodes」プロパティを持っています(飽くまで例です)。  そのためLimListもCListも本体と制限値、処理を半ば切り離すような形でLimBox<T>、CListActionBox<T>を用意したにいたります。  宣言場所のみ、または許可された範囲内でのみ制限や処理をいじれるようにするためにとった苦肉の策です。結果として、いわば「public」のような「internal」になったかと思います。

koumei000
質問者

補足

下記のstringに対応する云々は、お分かりかと思いますが文字列長だけではなく開始、終了の文字の判別、含まれているかどうかなどの判別も行います。

回答No.18

(ん~まぁ、仮に最善の構造になってるとして) ここまでの情報からだと「単に変形させる」だけとすれば こういう書き方も可能ではないかと思うのですが こういうのだとダメな理由はありますか? using System; namespace Controled { //エラーチェックはどのタイミングでどう行われるべきか現状分からないので省略します。 public class ActionBox<GETTER, SETTER> { public GETTER ItemGetter { get; set; } public SETTER ItemSetter { get; set; } } public class List<T> { //Func<int, T>やAction<int, T>のかわりにデリゲートを使っても良いでしょうが readonly ActionBox<Func<int, T>, Action<int, T>> _actionBox; public int Num { get; set; } //実験用 public T Data { get; set; } //実験用 public T this[int i] { get { return _actionBox.ItemGetter(i); } set { _actionBox.ItemSetter(i, value); } } public void Action1(int num, T data){ Num = num; Data = data; } //実験用 public Func<int, T> GetFunc { set { _actionBox.ItemGetter = value; } } public Action<int, T> SetFunc { set { _actionBox.ItemSetter = value; } } public List(){ _actionBox = new ActionBox<Func<int, T>, Action<int, T>>(); SetFunc = Action1; } } } フォームアプリのFormのコンストラクタで試す。 Controled.List<int> items = new Controled.List<int>(); items.GetFunc = (int x) => { return x + 10; }; items[10] = 100; Text = items[10] + " " + items.Num + " " + items.Data; 結果 20 10 100 関数とデータは近くに置いてないと無駄に分かりにくくなってしまったりするので (オブジェクト指向に反する) 継承と仮想関数で解決できるんならそれに越したことはないんですが また、「インデクサを使うからには」連想配列的(ハッシュ)的な動きをするとか、そのオブジェクトが配列操作メインの物である ような形じゃないと無駄に分かりにくくなってしまったりすると思います。(上記実験では実際の用途が分からなかったので、最終的なフォームの呼び出し側だけみても分かりにくいコードになっています)

koumei000
質問者

お礼

 ご指摘ありがとうございます。  このような構造にした意図が伝わりづらかったと思うのでまとめさせてもらいます。 ・まず、CList<T>の働きは、既存のList<T>の機能に加え、値のチェックを行う機能をつけたもの。 ・CListActionBox<T>は基本的にCList<T>と同じ場所でフィールド変数として宣言され、そのクラス内のコンストラクタ内でCListの初期化時にCListActionBoxが引数として渡される。 ・既存の「Action」、「Fanc」を用いなかったのは引数の内容を分かりやすくするため(ライブラリなので丁寧目に)。 public class SampleClass { private CListActionBox<int> _ageActinons; private CList<int> _ages; public CList<int> Ages { get { return _ages; } } // - - - - - - - - - - - - - private CListActionBox<string> _messageActions; private CList<string> _messages; public CList<string> Messages { get { return _messages; } } // - - - - - - - - - - - - - public SampleClass() {   // ↓のとき、_ageActionsの読み取り専用フィールド   // DefaultItemGetter、DefaultItemSetter   // DefaultItemAdder、DefaultItemRemoverに   // (index) => { return _bodyArray[index]; }   // (index, value) => { _bodyArray[index] = value; }   // Add(T item)の根幹部分   // Remove(T item)の根幹部分   // が代入されます。   _ages = new CList<int>(out _ageActions);   _ageActions.ItemGetter = DefaultItemGetter;   _ageActions.ItemSetter = (index, age) =>   {     if ( age < 0 || 200 < age )       throw new ArgumentOutOfRangeException("item");     _ageActions.DefaultItemSetter(index, age);   }   _ageActions.ItemAdder = (age) =>   {     if ( item < 0 || 200 < age )       throw new ArgumentOutOfRangeException("item");     _ageActions.DefaultItemAdder(age);   }   _ageActions.ItemRemover = _ageActions.DefaultItemRemover;   ……… } // -------------------------------------------------- // 使用例 public void Main(string[] args) { int loop = 10; var sample = new SampleClass(); var ages = new int[loop] { 5, 4, 3, 2, 1, 0, -1 , 2, 3, 4 }; // i = 6のとき例外が発生。 for ( int i = 0; i < loop; i++ )   sample.Ages.Add(ages[i]; } // ---------------------------------------------- のような感じです。CList<T>内部の挙動を監視するための動作をSampleClassの内部で設定しています。

回答No.17

なるほど。 つまり CListActionBox<T> は派生しない使い方が基本的ってことでしょうか? う~ん コードを見て冷静に考えれば考えるほど 実際にどういう状況でこれらのクラスを使いたいのかが分からなくなってきました。 仮想関数では出来ないぐらいに自由な イベントハンドラの任意関数版 を作りたいって感じでしょうか?

koumei000
質問者

お礼

 解答ありがとうございます > 派生しない使い方が基本的ってことでしょうか?  確かに基本的にはそうですが、派生します。具体的には自作コントロール内で各データ郡をより効率的に管理できる機能を持たせたものに派生します。

関連するQ&A

  • C#で、デリゲートからその関数の名前を取得する方法

    次のコードを見てください。コメントにあるように デリゲートを引数とする関数内部で、そのデリゲートが受け取った関数の関数自身の名前を取得しようとしています。どうすればいいでしょうか? using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace ラムダ式 { public partial class Form1 : Form { public Form1() { InitializeComponent(); //引数aとbの初期値 this.textBoxA.Text = "10"; this.textBoxB.Text = "5"; } //int型を返し(I)int型2つを引数にする関数のデリゲート public delegate int I_II(int a, int b); public static int 足し算(int a, int b) { return a + b; } public static int 引き算(int a, int b) { return a - b; } public static int 掛け算(int a, int b) { return a * b; } public string 二項演算(I_II 演算方法) { //ここでは、演算方法.tostring()を使って"足し算" や"引き算"などの //関数名を得ようとしているが。この方法だと,デリゲートの名前 //すなわち I_II が帰ってきてしまう //どうすれば デリゲートが参照している関数名 ”足し算”や"引き算など" //を得ることができますか? string 関数名 = 演算方法.ToString(); return 関数名 + ": " + 演算方法(int.Parse(textBoxA.Text), int.Parse(textBoxA.Text)).ToString() + "\r\n"; } private void button1_Click(object sender, EventArgs e) { textBox結果表示.Text = ""; textBox結果表示.Text += 二項演算(足し算); textBox結果表示.Text += 二項演算(引き算); textBox結果表示.Text += 二項演算(掛け算); } } }

  • C#で実行時にメソッドの返り値の型を変化させる

    C# で、実行時にメソッドの返り値の型を変化させることは可能でしょうか? たとえば、 public class MyData { object o; public void setValue( object a ) { o = a; } public object getValue() { return o; } } というクラスがあるとき、 static void Main(string[] args) { MyData a = new MyData(); a.setValue( 3 ); Console.WriteLine( a.getValue().GetType().ToString() ); int i = (int)a.getValue(); } というコードを実行すると、 System.Int32 と表示されます。Main の 4 行目で、(int)のキャストをはずすと、object から int への暗黙の変換はできませんというコンパイルエラーになります。 この(int)のキャストをしなくてもエラーにならないような getValue の関数はできないでしょうか? o は、数値型であるとします。 たとえば、MyData に、 public int getInt() { return (int)o; } とすれば、必ず int を返すようなメソッドはできると思うのですが、これだと、getByte() や、getDouble() などのように、考えられるすべての型を想定してメソッドを作ることになってしまいます。 そうではなく、getValue() で、少なくとも数値型の暗黙の変換はしてくれるようなことにできないでしょうか。 よろしくお願いします。

  • C#で別スレッドからメインformをアクティブ化

    質問番号:7352165で質問中の者です。 デリゲートとInvokeを使ったスレッドでは、スレッド実行中にイベントが発生しないので止む無く直接スレッドを起動しているのですが、この方法ではメインformのTextBoxなどに直接アクセスできません。 それでアクセスするメソッドをデリゲート+Invokeで呼んでおり、TextBoxの表示は正常に動作していますが、フォーカスをメインformに移動させる為にActivate();メソッドを記述すると「フィールド初期化子は静的でないフィールド、メソッド、または……を参照できません」の記述エラーとなります。 あまり理解できていないので基本的な使い方が間違っているかも知れませんが、何か解決策があればお教え下さい。 public void FormActive()  ← メインform(fmTax)に記述 {   this.Activate(); } private delegate void ActivDelegate(); ← 別スレッドに記述 ActivDelegate activDelegate = delegate() {   fmTax.FormActive(); ← ここにエラー表示 };

  • デリゲートで子から親フォームのメソッド実行について

    お世話になります。 .NET C#で開発をしております初心者です。 下記の様なデリゲートで子フォームから親フォームのメソッドを実行 させようとしています。 すると、parent2.MeisaiSyutoku(); の部分で エラーが発生してしまいます。 (エラー内容:NullReferenceExceptionはハンドルされませんでした。        オブジェクト参照がオブジェクト インスタンスに設定されていません。) 同じ子フォームで(親フォームは違いますが)、もう1つデリゲートをやっているのですが それも何か悪かったりするでしょうか。 下記のデリゲートで、デリゲート(2)はちゃんと実行されますが、デリゲート(1)の方でエラー となってしまいます。 どなたかご親切な方、違う方法でも構いませんので、子フォームから 親フォームのメソッドを実行する方法を教えて下さいます様、 宜しくお願い致します。      記 デリゲート(1) 子フォーム側 parent2; //親フォームの参照 public void setOya2(案内書 parent) { this.parent2 = parent; //親フォームから参照を受け取って保持する } private void button2_Click(object sender, EventArgs e) { ~イベント処理~ parent2.MeisaiSyutoku(); //案内書.csのメソッド実行 } 親フォーム側 private void button4_Click(object sender, EventArgs e) { Global.openMOTO = 1; 台帳 n台帳 = new 台帳(); n台帳.setOya2(this); n台帳.Show(); } private delegate void ctlFromChild(); public void MeisaiSyutoku() { new Thread(new ThreadStart(delegate { Invoke((ctlFromChild)delegate { Get_MeisaiSyutoku(); }); })).Start(); } デリゲート(2) 子フォーム側 送り状作成 parent1; //親フォームの参照 public void setOya1(送り状作成 parent) { this.parent1 = parent; //親フォームから参照を受け取って保持する } private void fpSpread1_CellDoubleClick(object sender, CellClickEventArgs e) { ~イベント処理~ parent1.changeTextBox4(zOtodokeSaki);         } 親フォーム側 private void button1_Click(object sender, EventArgs e) { Global.openMOTO = 0; 台帳 n台帳 = new 台帳(); n台帳.setOya1(this); n台帳.Show(); } private delegate void ctlFromChild(); public void changeTextBox4(string str) { new Thread(new ThreadStart(delegate { Invoke((ctlFromChild)delegate { this.textBox4.Text = str; }); })).Start(); }

  • Visual Basic 2005 でのデリゲート、Invokeについて

    卒論の関係で、Visual Basic 2005 Express Editionを使用して、システムを構築しています。 スレッドまたはフォームが複数あるため、デリゲートを使用することになったのですが、invokeの対象であるメソッドで引数を使用することはできるのでしょうか? 引数なしの場合、現時点では次のように記述しています。 A.show() A.Invoke(New MethodInvoker(AddressOf A.Status_Timer)) Public Sub Status_Timer()   処理 End Sub MethodInvokerは、デリゲート宣言なしでinvokeを使えることができ、本来?のデリゲート宣言して、invokeを使う場合は以下のようになります。 A.show() A.Invoke(New SetFocusDelegate(AddressOf A.Status_Timer)) Delegate Sub SetFocusDelegate() Public Sub Status_Timer()   処理 End Sub ここで、Status_Timer()に引数を指定して、たとえば、 Public Sub Status_Timer(ByVal data As integer)   処理 End Sub とした場合、invokeでの記述がうまくいきません。 もともと、invokeではそんなことはできないかもしれませんが、何か方法ありますでしょうか?現時点では、引数を使用することができないので、スレッドまたはフォーム間で、プロパティを使用して、情報を渡しています。以下のような形です。できれば、プロパティを使用したくないのですが・・・ Public Property test() As state Get Return _test End Get Set(ByVal value As state) _test = value End Set End Property

  • C# 匿名メソッドについて

    http://www.atmarkit.co.jp/fdotnet/csharp20/csharp20_05/csharp20_05_02.html 匿名メソッドを勉強しています。 上記のサイトの最初のソースで using System; delegate void MyAction(); class Program { static MyAction CreateMethod() { string message = "Hello! World!"; return delegate() { Console.WriteLine(message); }; } static void Main(string[] args) { MyAction action = CreateMethod(); action(); // 出力:Hello! World! } } このソースに対して、 >>常識的に考えればこのプログラムは動作しないはずである。 >>なぜなら、変数messageはCreateMethodメソッドからリターンした瞬間に消滅するが、 >>匿名メソッドが呼ばれるのはその後だからである。 と書かれていますが、 私にはその不思議さがわかりません。 まず、インスタンスされたクラスは初めにMainを読みに行き、 MyAction action = CreateMethod();でCreateMethod()を実行する。その実行した中でreturn”message”が結果的にされる。 そして、それがactionに代入されるという流れだと思うのですが、なぜ、これが不思議なのでしょうか?

  • ActionScript(3.0)の命名規則について

    flashデベロッパーの方に参考意見をいただきたいです。(それ以外の方も大歓迎です) 変数の命名規則なのですが、皆様はどのような形で規則性を持たせていますか?参考書などを見ると結構それぞれに違う規則があるように感じました。 例えば今自分が考えているモノとしては ・private変数には_hogeのようにアンダースコアを。 ・public変数は通常通りhogeで。(getterも同様に) ・クラス変数は__hogeのようにアンダースコア2つで。 このくらいしか分類していないのですが、他にも引数やローカル変数にはこれがいい、とか、その他慣例やおススメがあれば是非ご意見をいただけますでしょうか。 よろしくお願いいたします。

    • ベストアンサー
    • Flash
  • C#のスレッド動作について

    下記はスレッドの中で永久ループさせるテストプログラムで、1秒毎にテキストボックス内の数値をインクリメントします。 【問題点1】 ※1と※2のコマンドを削除した状態(※3のみ)で正常な動作を期待していたのですが、実際にはフリーズ状態となり、カウント値が表示されません。 ※2のApplication.DoEvent()を実装するか、※3の替わりに※1に実装すると正常動作となります。 ExecThread実行中は他の処理を出来なくても、これを抜けた時点で表示処理に移るので表示される筈と思っていたのですが違う様です。 【問題点2】 Invokeの替わりにBeginInvokeを使えばExecThread実行中でも他の処理と並列処理されると思っていたのですが、スレッドを2個用意して試したところInvokeと全く変わらず、やはりフリーズ状態となります。 【問題点3】 ExecThreadを匿名メソッドにすると「フィールド初期化子は、静的でないフィールド、メソッド、又はプロパティ'iCount'を参照できません」のエラーとなり、「iCount」をstatic変数にするとOKになります。 匿名メソッドではインスタンス変数は使えないのでしょうか。 上記3項目についてネットで調べたのですがその様な記述は見当たりませんでした。 何か使い方が間違っているのでしょうか? 間違い点など、ご指摘頂ければ有難いです。 どうぞ宜しくお願いします。 private void ExecWorker() ← スレッド {   while (true)   {     Invoke(new Exec1Delegate(this.ExecThread)); ← BeginInvokeを使っても症状は同じ     iCount++;     Thread.Sleep(1000); ← ※1 このSleepが無いとフリーズする     Application.DoEvent(); ← ※2 これがあると※1のSleepが無くてもOK   } } delegate void ExecDelegate(); private void ExecThread() {   lbThread.Text = iCount.ToString(); ← 匿名メソッドにするとエラーになる   Thread.Sleep(1000); ← ※3 (※1のSleepと同時実装はしない) }

  • C#のループについて

    現在C#でジャンケンゲームの課題に取り組んでいるのですが、ループ処理や各メソッドに対しての変数にエラーがでてしまい、修正方法が分からず、どなたか教えて頂けないでしょうか? ・ユーザはグー、チョキ、パーをそれぞれ1、2、3の数字で入力する。 ・CPUは乱数を使って出す手を選ぶ。 ・5回勝負として、人間とコンピュータの勝った回数を数え、勝敗がつくたびに1回ずつ表示する。    あいこは決着がつくまで再勝負。途中でどちらかが3勝しても、5回最後まで勝負を続ける。   ・指定された範囲以外の値を入力したら負けにする 【実行例】  ユーザ名を入力してください:goto  手を入力してください(グー1、チョキ2、パー3): 1  CPU:チョキ  WIN  goto:1勝、CPU:0勝    手を入力してください(グー1、チョキ2、パー3): 3  CPU:パー  DRAW    手を入力してください(グー1、チョキ2、パー3): 3  CPU:チョキ  LOSE  goto:1勝、CPU:1勝    手を入力してください(グー1、チョキ2、パー3): 0  LOSE(反則負け)  goto:1勝、CPU:2勝    (中略)    goto:3勝、CPU:2勝  gotoさんの総合勝利です! using System; namespace Ensyuu007 { static class Program { static string? Myhand; static int CntWin = 0; //勝利回数 static int CntLose = 0; //敗北回数 static int CntDraw = 0; //引分回数 //ユーザー名の入力 static void Main(string[] args) { string EnterName = Console.ReadLine(); Console.WriteLine("ユーザ名を入力してください: {0}", EnterName); Console.ReadLine(); } //じゃんけんを5回行います。 for (int GameCnt = 0; GameCnt <= 5; GameCnt++) { //正しく入力されたかチェックを行うメソッド。 static string Check(ref string Myhand) { static = Console.ReadLine(); Console.WriteLine("手を入力してください(グー1、チョキ2、パー3):{0}", Myhand); //正しく入力されたかチェックします。 Check(ref Myhand); //0,1,2が入力された場合 if (Myhand.Equals("1") || Myhand.Equals("2") || Myhand.Equals("3")) { //入力した数字をそのまま返します。 return Myhand; } //1,2,3以外が入力された場合 else { Console.WriteLine("LOSE(反則負け)"); return Myhand; } } //じゃんけんを開始するメソッド。 static void Start() { //コンピューターとじゃんけんさせます。 Janken(ref Myhand); Console.ReadLine(); } //コンピュータと自分の入力した手を判別するメソッド static void Janken(ref string Myhand) { // Random クラスの新しいインスタンスを生成する Random ran = new System.Random(); //コンピュータの出す手を1以上3以下に設定する。 string[] com = new string[] { "1", "2", "3" }; string con = ran.Next(3).ToString(); //配列型、変数teに出す名前を設定 string[] te = { "グー", "チョキ", "パー" }; //コンピュータが勝利した場合 if (((Myhand == "1") && (con == "3")) || ((Myhand == "2") && (con == "1")) || ((Myhand == "3") && (con == "0"))) { Console.WriteLine("あなた:" + te.GetValue(int.Parse(Myhand))); Console.WriteLine("コンピュータ:" + te.GetValue(int.Parse(con))); Console.WriteLine("LOSE"); CntLose++; //敗北回数に加算 } //自分が勝利した場合 else if (((Myhand == "1") && (con == "2")) || ((Myhand == "2") && (con == "3")) || ((Myhand == "3") && (con == "1"))) { Console.WriteLine("あなた:" + te.GetValue(int.Parse(Myhand))); Console.WriteLine("コンピュータ:" + te.GetValue(int.Parse(con))); Console.WriteLine("WIN"); CntWin++; //勝利回数に加算 } //あいこだった場合 else { Console.WriteLine("あなた:" + te.GetValue(int.Parse(Myhand))); Console.WriteLine("コンピュータ:" + te.GetValue(int.Parse(con))); Console.WriteLine("DRAW"); CntDraw++; //引分回数に加算 } } } static void Resurut() { if (CntWin > CntLose) { Console.WriteLine("総合勝利です"); } else if (CntLose < CntWin) { Console.WriteLine("CPUの総合勝利です"); }

  • C言語の関数の仮引数の記述

    関数の仮引数の( )の中に何の変数を書いたらいいかいまいちつかめていません。関数の実行文や、もしくはmain関数の呼び出し実行文とどんな互換性があってどの変数を書いていいかわからないので教えてください。一応わかる部分を少し書きますがたとえば、変数をコピーするint copy( int a, int b )ってゆーのがあるとすれば、bをaにコピーするために必要となる変数a、bを( int a, int b )と書けばいいと思うんですがどうでしょう?仮引数部分にはmain関数に返す値となる変数だけを書くとどうなるんでしょう? なんかわかりにくくてすいませんが、答えになってなくても関係することであれば返信ください。 あとコンパイラーはCygwinで、理解度はfor文やif文や関数、配列などの基本はだいたいOKです。ポインタとかその他の応用についてはわかりません。

専門家に質問してみよう