C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[8]: ジェネリック型でデリゲートの記述について


(過去ログ 107 を表示中)

[トピック内 11 記事 (1 - 11 表示)]  << 0 >>

■63853 / inTopicNo.1)  ジェネリック型でデリゲートの記述について
  
□投稿者/ らぐんす (1回)-(2012/10/19(Fri) 10:44:00)

分類:[.NET 全般] 

//@デリゲートの定義
public delegate IEnumerable<T> GetInfosHandler<T>();


//Aデリゲート型の変数
public GetInfosHandler<T> GetInfos;


//Bこんな感じで使いたい
if (GetInfos != null)
IEnumerable<T> infos = GetInfos<T>();

のようにジェネリックのデリゲートを使用したいのですが、実際にはAのような記述はできません。
根本的に違うというのなら、ご教授していただければ幸いです。
よろしくお願い致します。
引用返信 編集キー/
■63855 / inTopicNo.2)  Re[1]: ジェネリック型でデリゲートの記述について
□投稿者/ 魔界の仮面弁士 (67回)-(2012/10/19(Fri) 11:18:47)
No63853 (らぐんす さん) に返信
> こんな感じで使いたい

こういうことでしょうか?

class Class1<T>
{
    public delegate IEnumerable<T> GetInfosHandler<T>();
    public GetInfosHandler<T> GetInfos;
    public void Test()
    {
        if (GetInfos != null)
        {
            IEnumerable<T> infos = GetInfos();
        }
    }
}

引用返信 編集キー/
■63856 / inTopicNo.3)  Re[2]: ジェネリック型でデリゲートの記述について
□投稿者/ らぐんす (2回)-(2012/10/19(Fri) 12:17:53)
魔界の仮面弁士様、ありがとうございます。
そうです。
実はClass1はWindows.Forms...TextBoxの継承クラスなのですが、
今まではIEnumerable<T>の部分がDataTableだったので、Class1のままで行けたのですが
Class1<T>のように変更すると利用している側でどのような修正になるのか、ちょっと想定できません。
うーん、もう少し粘ってみます。





引用返信 編集キー/
■63858 / inTopicNo.4)  Re[3]: ジェネリック型でデリゲートの記述について
□投稿者/ 魔界の仮面弁士 (68回)-(2012/10/20(Sat) 00:06:25)
No63856 (らぐんす さん) に返信
> 今まではIEnumerable<T>の部分がDataTableだったので、Class1のままで行けたのですが
> Class1<T>のように変更すると利用している側でどのような修正になるのか、ちょっと想定できません。
> うーん、もう少し粘ってみます。

Class1 を利用する側(Form?)が、型パラメータ T を提供するのですよね。

フィールドやプロパティには型パラメータを指定できないので、
先のように Class1 型自体が T を持つようにするか…それがだめならば
setter/getter のメソッドを用意して、そこで型パラメータを得るとか。


public class TextBoxEx : TextBox
{
    public delegate IEnumerable<T> GetInfosHandler<T>();

    private Delegate internalGetInfos;
    public void SetInfos<T>(GetInfosHandler<T> proc) { internalGetInfos = proc; }
    public GetInfosHandler<T> GetInfos<T>(){ return internalGetInfos as GetInfosHandler<T>; }

    public void Test<T>()
    {
        GetInfosHandler<T> infos = GetInfos<T>();
        if (infos != null)
        {
            IEnumerable<T> enums = infos();
        }
    }
}


// textBoxEx1.SetInfos<int>(delegate { return new[] { 1, 3, 5, 7, 9 }; });
// textBox1.Test<int>();

引用返信 編集キー/
■63859 / inTopicNo.5)  Re[3]: ジェネリック型でデリゲートの記述について
□投稿者/ Azulean (52回)-(2012/10/20(Sat) 01:05:36)
No63856 (らぐんす さん) に返信
> 実はClass1はWindows.Forms...TextBoxの継承クラスなのですが、
> 今まではIEnumerable<T>の部分がDataTableだったので、Class1のままで行けたのですが
> Class1<T>のように変更すると利用している側でどのような修正になるのか、ちょっと想定できません。

個人的にはコントロールクラスが Generic になるのはおすすめできません。.NET のバージョンによってはシリアライズで不具合を引いたり、デザイナでトラブルかもしれないので。

もう少し具体的な型で利用イメージを共有していただけるとアドバイスしやすいかと思います。
int 型とか、double 型とかで実際の型とは違う型で代用するとして、どういった使い方をしたいかなど。


ただ、既存コードに影響を与えず、汎化させるのは難しいかもしれません。
既存の TextBox 継承クラスのノウハウを別クラスに切り出して、TextBox 継承クラスからはそのクラスに委譲する形にして、別の TextBox 継承クラスを作ることも考えた方がいいかもしれません。
引用返信 編集キー/
■63870 / inTopicNo.6)  Re[4]: ジェネリック型でデリゲートの記述について
□投稿者/ らぐんす (4回)-(2012/10/22(Mon) 21:09:30)
魔界の仮面弁士様、Azulean様、ありがとうございます。

場面としましては、TexBox上で特定のキーが押下された場合にDataGridViewだけの子画面がポップアップされます。
子画面をNEWする際にでDataTableを引数に渡してDataGridViewにバインドしております。

----------↓以下ソース抜粋です(読みにくい点はご了承ください)----------

/***現行はDataTableを取得するデリゲードを定義していました。***/
public delegate DataTable GetTableHandler();

/***共通のテキストクラス***/
public partial class BaseTextBox : TextBox {
//デリゲートのハンドラ
public GetTableHandler GetTable;

/***共通のフォームクラス***/
public partial class BaseForm : Form {
//特定キーが共通のテキストクラス上で押下されたら、
//子画面をポップアップするために目的のデリゲートを使用します
protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) {
BaseTextBox txt = this.ActiveControl as BaseTextBox;
//具象フォーム側で使用されるといいネ!
if (txt.GetTable != null) {
DataTable table = txt.GetTable();
//ポップアップするよ
PopForm frm = new PopForm(table);
if (frm.ShowDialog(this) == DialogResult.OK) {

/***具象フォームで以下のように使用しております。***/
public partial class MainForm : BaseForm {
//こんな感じで使用しています。
txt_CSTCD.GetTable = ()=> 取引先のコード&名称&;カナのDataTableを返す記述をしております。

--------------------------------------------------------------------------------
今まではDataTableクラスだったので取引先だろうが部門だろうが万能だったのですが、
これからは取引先Infoなり部門Infoのジェネリックしようと目論んで何度もコンパイラに返り討ちされます。

魔界の仮面弁士様>
テクすごい参考になります。
でもDelegateクラスでas句を使っているのはある意味でキャストでしょうか?
ジェネリックを使用するうえで何か違和感があります。

Azulean様>
私もWindows.Formのクラスをジェネリックにするのは気持ち悪いです。

以上よろしくお願い致します。

引用返信 編集キー/
■63871 / inTopicNo.7)  Re[5]: ジェネリック型でデリゲートの記述について
□投稿者/ 魔界の仮面弁士 (69回)-(2012/10/22(Mon) 22:17:33)
No63870 (らぐんす さん) に返信
> でもDelegateクラスでas句を使っているのはある意味でキャストでしょうか?

「(型名)インスタンス」のキャストでも。


> ジェネリックを使用するうえで何か違和感があります。

ジェネリック型の「クラス」や「メソッド」を用意する場合には、
 public void Test<T>() {}
のように、型パラメータを記述できますが、ジェネリック型の「変数」を用意する場合には、
 List<T> x;
ではなく、
 List<Int16> a;
 List<Int32> b;
のように、具体的な型を指定しなければなりません。


デリゲートやイベントも同様で、「型の宣言時」には <T> と書けますが、
デリゲートインスタンスを格納する変数には、具体的な型指定が
必要になってくるかと思います。EventHandler<T> と同様に。
引用返信 編集キー/
■63872 / inTopicNo.8)  Re[5]: ジェネリック型でデリゲートの記述について
□投稿者/ Azulean (53回)-(2012/10/22(Mon) 22:25:10)
2012/10/22(Mon) 22:25:45 編集(投稿者)

非ジェネリックなクラスとなるためには、そのクラスのコード内ですべての型パラメーターが解決しているか、メソッドの型パラメーターをつけてもらう形にする必要があります。
「ジェネリックで違和感を覚える」と表現されていますが、非ジェネリックのクラスとするために、メソッドのみジェネリックにしているので仕方ないものです。その違和感を払拭するなら、クラス自体をジェネリックにしなければなりませんので、あなたの望みと反します。

結局のところ、ジェネリックではなく、DataTable とその継承クラスのように、共通の基底クラス、あるいは共通のインターフェースを用意するしかないと思います。

今の DataTable バージョンも DataTable クラスに用意されているプロパティ、メソッド、イベントしか使っていないですよね?
これに対して、未知の T に対しては何も操作できません。
引用返信 編集キー/
■63883 / inTopicNo.9)  Re[6]: ジェネリック型でデリゲートの記述について
□投稿者/ らぐんす (5回)-(2012/10/24(Wed) 10:16:52)
魔界の仮面弁士様、Azulean様、度々ありがとうございます。

>魔界の仮面弁士様
ご教授してくださった作戦でトライしてみたのですが、結局はTest<T>メソッドを呼出す際のTを具体的に記述しないとダメなので、共通フォーム内で用いるのは無理でした…

>Azulean
さすがにポップ画面だけはジェネリックのFormクラスにするつもりでした。
Infoクラスはpublicフィールドのみ持つクラスです。[DataContract]、[DataMember]の属性を付けてやればReflectionでDataTable版のカラム名と同様のアクセスが可能では?考えてました(まだトライしてないので分かりません)

自分の未熟さを痛感する次第です。
引用返信 編集キー/
■63888 / inTopicNo.10)  Re[7]: ジェネリック型でデリゲートの記述について
□投稿者/ Azulean (54回)-(2012/10/24(Wed) 22:14:41)
2012/10/24(Wed) 22:17:46 編集(投稿者)

No63883 (らぐんす さん) に返信
> ご教授してくださった作戦でトライしてみたのですが、結局はTest<T>メソッドを呼出す際のTを具体的に記述しないとダメなので、共通フォーム内で用いるのは無理でした…

(これまでの流れからして中間地点と思える)共通フォームをジェネリックとしたくないのなら、ジェネリック路線は無理だと思います。


> Infoクラスはpublicフィールドのみ持つクラスです。[DataContract]、[DataMember]の属性を付けてやればReflectionでDataTable版のカラム名と同様のアクセスが可能では?考えてました(まだトライしてないので分かりません)

これだけだと、object 型で渡せばいいじゃんということになってしまうんですよね。
リフレクションで属性を探すのであれば、型安全とは言えませんし…。
出し入れだけでも、安全にしたいってことなのかなぁ。

// C# 4.0 以上の共変性で満足できるシナリオだろうか?
引用返信 編集キー/
■63891 / inTopicNo.11)  Re[8]: ジェネリック型でデリゲートの記述について
□投稿者/ らぐんす (6回)-(2012/10/25(Thu) 10:32:40)
<Azulean様
ありがとうございます。自分なりにやってみて共通フォームにジェネリックメソッドを追加しそれを具象フォームから確定型で呼出す方法に書き換えたら、それなりの改造で何とか実現できました。
「共変性」というキーワード情報ありがとうございます。私の中ではC#3.0で止まっているため勉強してみます。(環境がVS2008なので2年置きに買う余裕がありません、VS2012は購入予定ですが)

恥ずかしながら今回の件も結局は、WCF化から派生致しました。
私のように中途半端な開発者は、とにかく自分でやってみないと身に付きませんのですが、間違った方向に進んでしまう困ってしまうので、ここの掲示板の皆様方に助言なり指摘なりを頂く事が大変に有益になっております。
魔界の仮面弁士様・Azulean様、色々とありがとうございました。
ひとまず解決済ということでクローズ致します。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -