トップ回答者
クラスの型を引数として渡すには

質問
-
次の様な、クラスがあります。
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」も引数で渡す
方法ってないでしょうか?
毎度、コーディングの仕方という基本的な質問で申し訳ないのですが、
ご教授の程、宜しくお願い致します。
回答
-
外池です。外しているかもしれませんが・・・・、
Type型の、Equals と IsSubclassOf をOrで結ぶような演算で判断してやればよいのでは?
Code Snippetclass 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つ返りますが・・・。
すべての返信
-
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)なのか派生コントロールなのかを
判別するところは省略できないのですかね?
-
IsAssignableFrom メソッドの方が適当でしたかね。
どこから delegate が出て来ましたか?
// 個人的にはこんなのでいいや。まあこんなの使うことないけど
Code Snippetpublic 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;
}
}
-
外池です。外しているかもしれませんが・・・・、
Type型の、Equals と IsSubclassOf をOrで結ぶような演算で判断してやればよいのでは?
Code Snippetclass 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つ返りますが・・・。
-
外池さん、回答ありがとうございます。
>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」ってどういう意味なんでしょう?
コンパイルが通らないのですが。
-
@ぶるーのさんこんにちは
型を引数にということでまさにジェネリックと思いましたが、不定個の引数はだめですね。
HongliangさんのおっしゃるようにIsAssignableFromが良いみたいです。
findControl.AddRange(allControl.FindAll(delegate(Control item) { return typ.IsAssignableFrom(item.GetType()); }));
GetControls<T>(this Control parent)
これは2008の拡張メソッドです。2005では通りません。