web-dev-qa-db-ja.com

型がパラメーターなしのコンストラクターを提供するかどうかを確認するにはどうすればよいですか?

実行時に既知の型がパラメーターなしのコンストラクターを提供するかどうかを確認したいと思います。 Typeクラスは有望なものをもたらさなかったので、リフレクションを使用する必要があると思いますか?

94
mafu

Typeクラスisリフレクションです。できるよ:

_Type theType = myobject.GetType(); // if you have an instance
// or
Type theType = typeof(MyObject); // if you know the type

var constructor = theType.GetConstructor(Type.EmptyTypes);
_

パラメーターなしのコンストラクターが存在しない場合はnullを返します。


プライベートコンストラクターも検索する場合は、少し長いものを使用します。

_var constructor = theType.GetConstructor(
  BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, 
  null, Type.EmptyTypes, null);
_

値の型には注意事項があります。これは、 デフォルトのコンストラクタを持つことは許可されていません です。 _Type.IsValueType_ プロパティを使用して値タイプがあるかどうかを確認し、 Activator.CreateInstance(Type) ;を使用してインスタンスを作成できます。

157
Alex J
type.GetConstructor(Type.EmptyTypes) != null

structsでは失敗します。拡張する方が良い:

public static bool HasDefaultConstructor(this Type t)
{
    return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}

enumsでもデフォルトのパラメーターなしのコンストラクターがあるため成功します。また、リフレクションの呼び出しが行われないため、値型の速度がわずかに向上します。

13
nawfal

はい、Reflectionを使用する必要があります。ただし、GetType()を使用する場合は、すでにそれを行っています。

何かのようなもの:

var t = x.GetType();
var c = t.GetConstructor(new Type[0]);
if (c != null) ...
12
Henk Holterman

これは動作するはずです:

   myClass.GetType().GetConstructors()
                    .All(c=>c.GetParameters().Length == 0)
8
BrokenGlass

状況に応じて、ジェネリック型の制限を使用することもできます。

public void DoSomethingWith<T>(T myObject) where T:new() {...}

上記のメソッド宣言は、パラメーターのないコンストラクターでインスタンス化できる任意のオブジェクトにパラメータータイプを制限します。ここでの利点は、コンパイラがパラメータレスコンストラクターを持たないクラスでメソッドを使用しようとする試みをキャッチすることです。そのため、コンパイル時に型がSOMEWHEREであることがわかっている限り、これは動作し、以前の問題。

もちろん、型が実行時にのみ実際に知られている場合(つまり、Activator.CreateInstance()を使用して文字列または構築された型に基づいてオブジェクトをインスタンス化する場合)、これは役に立ちません。私は通常、絶対的な最後のオプションとしてリフレクションを使用します。動的な土地に行ったら、動的な土地にとどまる必要があるためです。通常、何かを動的にインスタンス化してから静的に処理を開始することは困難であり、さらに面倒です。

4
KeithS

「公式」バージョンに興味がある人は、 。NET Reflector で次のことが見つかりました。

from:System.Activities.Presentation.TypeUtilities
inSystem.Activities.Presentation.dll、Version = 4.0.0.0

public static bool CanCreateInstanceUsingDefaultConstructor(this Type t) => 
                t.IsValueType || !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null;

t.IsAbstractのチェックに注意してください。これは、このページのどこにも記載されていません。

スタックフレームを1つずつ微最適化する場合は、次のようにGetConstructorコールアウトを展開することもできます。

…t.GetConstructor(BindingFlags.Public|BindingFlags.Instance, null, Type.EmptyTypes, null)…
1
Glenn Slayden

はい、反射を使用する必要があります。

object myObject = new MyType();
Type type = myObject.GetType();
ConstructorInfo conInfo = type.GetConstructor(new Type[0]);
1
Mel Harbour

onlyオプションのパラメーターを持つコンストラクターを、真のパラメーターレスコンストラクターと同じように数える必要がありました。これをする:

myClass.GetType().GetConstructors()
    .All(c => c.GetParameters().Length == 0 || c.GetParameters().All(p => p.IsOptional))
1
Aaron D