none
クラスの型を引数として渡すには RRS feed

  • 質問

  • 次の様な、クラスがあります。

     

    public class TextBoxEx : TextBox {}

     

    次の処理では、b1は「true」、b2は「false」になるかと思いますが、

     

    TextBox textBox = new TextBox();

    TextBoxEx textBoxEx = new TextBoxEx();

    bool b1 = myMethod(textBox, typeof(TextBox));

    bool b2 = myMethod(textBoxEx, typeof(TextBox));

     

    public bool myMethod(Control control, Type type)

    {

        return control.GetType() == type;

    }

     

    このb1、b2を共に「true」にしたくて、次の様なメソッドを用意しました。

     

    public bool myMethod2(Control control)

    {

        return control is TextBox;

    }

     

    これで、b1、b2 共に「true」になるのですが、この「is」の後の「TextBox」も引数で渡す

    方法ってないでしょうか?

     

    毎度、コーディングの仕方という基本的な質問で申し訳ないのですが、

    ご教授の程、宜しくお願い致します。

     

    2008年3月31日 2:58

回答

  • 外池です。外しているかもしれませんが・・・・、

     

    Type型の、Equals と IsSubclassOf をOrで結ぶような演算で判断してやればよいのでは?

     

    Code Snippet

        class Program {
            static void Main(string[] args) {
                Cherry tree = new Cherry();
                Life cell = new Life();

                Console.WriteLine(IsItselfOrDerivedFrom(cell.GetType(),typeof(Life)));
                Console.WriteLine(IsItselfOrDerivedFrom(tree.GetType(), typeof(Life)));
            }
            static bool IsItselfOrDerivedFrom(Type testType, Type refType) {
                return (testType.Equals(refType) || testType.IsSubclassOf(refType));

            }
        }
        class Life {
        }
        class Plant : Life {
        }
        class Cherry : Plant {
        }

     

     

    Trueが2つ返りますが・・・。

    2008年3月31日 9:20

すべての返信

  • Type.IsSubclassOf メソッドもありますが、こういうのはメソッドにするのではなく直接 is/as 演算で判定すべきだと思います。

    2008年3月31日 3:26
  • Hongliangさん、回答ありがとうございます。

     

    >Type.IsSubclassOf メソッドもあります

     

    このメソッドもTextBoxコントロール自身と、TextBoxから派生したコントロールとでは

    同じ結果にならないんですね。

     

    bool b1 = textBox.GetType().IsSubclassOf(typeof(TextBox));
    bool b2 = textBoxEx.GetType().IsSubclassOf(typeof(TextBox));

    >直接 is/as 演算で判定すべきだと思います

     

    仰る通りだと思います。

    今回、質問に挙げたソースは、あくまでも例題で、

    本来は、Formに貼り付いているコントロールで、指定された条件に合致するコントロールを

    戻すメソッドに応用したいと考えてまして。

     

    public static List<Control> GetControl(Control control, Type[] getType)

    {

        List<Control> allControl = new List<Control>();

        foreach (Control ctl in this.Controls)

        {

            allControl.Add(ctl);

        }

        List<Control> findControl = new List<Control>();

        foreach (Type typ in getType)

        {

             findControl.AddRange(allControl.FindAll(delegate(Control item) { return item.GetType() == typ; }));

        }

        return findControl;

    }

     

    上記の様なメソッドに対し、

     

    List<Control> controlList = GetControl(this, new Type[] {typeof(TextBox), typeof(RadioButton)});

     

    の様に指定した場合、TextBoxとRadioButtonのコントロールを取得させたいのですが、

    この時、

     

    public class TextBoxEx : TextBox {}

     

    の様なTextBoxから派生したコントロールも条件に合致させたいと考えていて。

    ただ、delegate内でのGetType()メソッドによる型判定では、TextBoxとTextBoxExは別物に

    なってしまうのを救いたいと思いまして。

     

    それで、delegate内で、「is TextBox」や「is RadioButton」とできる様に、引数(変数化)に

    できれば、と。

    これが、本来のやりたい事です。

     

    結局は、基底コントロール(TextBoxやRadioButton)なのか派生コントロールなのかを

    判別するところは省略できないのですかね?

     

    2008年3月31日 8:35
  • IsAssignableFrom メソッドの方が適当でしたかね。

    どこから delegate が出て来ましたか?

     

    // 個人的にはこんなのでいいや。まあこんなの使うことないけど

    Code Snippet

    public static IEnumerable<T> GetControls<T>(this Control parent) where T : Control {

        foreach (Control c in parent.Controls) {

            T t = c as T;

            if (t != null) yield return t;

        }

    }

    2008年3月31日 9:16
  • 外池です。外しているかもしれませんが・・・・、

     

    Type型の、Equals と IsSubclassOf をOrで結ぶような演算で判断してやればよいのでは?

     

    Code Snippet

        class Program {
            static void Main(string[] args) {
                Cherry tree = new Cherry();
                Life cell = new Life();

                Console.WriteLine(IsItselfOrDerivedFrom(cell.GetType(),typeof(Life)));
                Console.WriteLine(IsItselfOrDerivedFrom(tree.GetType(), typeof(Life)));
            }
            static bool IsItselfOrDerivedFrom(Type testType, Type refType) {
                return (testType.Equals(refType) || testType.IsSubclassOf(refType));

            }
        }
        class Life {
        }
        class Plant : Life {
        }
        class Cherry : Plant {
        }

     

     

    Trueが2つ返りますが・・・。

    2008年3月31日 9:20
  • 外池さん、回答ありがとうございます。

     

    >Type型の、Equals と IsSubclassOf をOrで結ぶような演算で判断

     

    この合わせ技判定で、うまくいけそうです。

    使わせて頂きます。

     

     

    >static IEnumerable<T> GetControls<T>(this Control parent) where T : Control

     

    型パラメータの使用で「型」は指定できる様になったのですが、複数の「型」を指定

    したい場合はどうすれば良いのでしょうか?

     

    GetControlsメソッドをそれぞれの型で別々にコール?となると、このGetControlsメソッドを

    上位から直接コールさせられなくなるので(「型」を複数指定できるという仕様から)、

    結局はこの「型」を引数でもらえる手段が必要になってくるのですが。

     

     

    >GetControls<T>(this Control parent)

     

    この「this Control parent」ってどういう意味なんでしょう?

    コンパイルが通らないのですが。

     

    2008年4月1日 0:46
  • 複数の型を指定したいのであれば、私の例のrefTypeを配列にしてやって、判定式をforeachでグルグル回してやって、ひとつでもTureが返ればTure、全部外れればFalseということで。これは、もともと@ぶるーのさんのアイデアにもあったように思いますが。

     

    2008年4月1日 0:53
  •  @ぶるーのさんこんにちは

     型を引数にということでまさにジェネリックと思いましたが、不定個の引数はだめですね。

     HongliangさんのおっしゃるようにIsAssignableFromが良いみたいです。

     

            findControl.AddRange(allControl.FindAll(delegate(Control item) { return typ.IsAssignableFrom(item.GetType()); }));

     

     GetControls<T>(this Control parent)

     これは2008の拡張メソッドです。2005では通りません。


     

     

    2008年4月1日 1:29
  • 三輪の牛さん、回答ありがとうございます。

     

    >判定式をforeachでグルグル回してやって

     

    はい。

    型パラメータを使用した例を示して頂いたのですが、上位から引数としてもらうType型(の配列)と

    この型パラメータとのからめ方がわからなかったので、型パラメータの方式でやるならばどうすれば

    よいのかな?というので、前回の質問でした。

     

    >不定個の引数はだめですね

     

    ダメですか。

    やはり、外池さんが示して頂いた方式を応用させて頂きます。

     

    >これは2008の拡張メソッドです

     

    了解しました。

     

    皆様、いろいろありがとうございました。

     

    2008年4月1日 7:30