非静的メソッドで私は使用できthis.GetType()
、それはを返しますType
。Type
静的メソッドでどうすれば同じことができますか?もちろん、私はランタイムでのみ知られているtypeof(ThisTypeName)
ので、単に書くことThisTypeName
はできません。ありがとう!
非静的メソッドで私は使用できthis.GetType()
、それはを返しますType
。Type
静的メソッドでどうすれば同じことができますか?もちろん、私はランタイムでのみ知られているtypeof(ThisTypeName)
ので、単に書くことThisTypeName
はできません。ありがとう!
回答:
this.GetType()
静的メソッドと同等の1ライナーを探している場合は、以下を試してください。
Type t = MethodBase.GetCurrentMethod().DeclaringType
ただし、これは単にを使用するよりもはるかに高価ですtypeof(TheTypeName)
。
typeof(TheTypeName)
とにかく優れたリファクタリングツールで対処する必要があります。
他の回答ではまだ明確にされていないものがあります。これは、実行時にのみ利用できるタイプの考えに関連しています。
派生型を使用して静的メンバーを実行する場合、バイナリでは実際の型名は省略されます。たとえば、次のコードをコンパイルします。
UnicodeEncoding.GetEncoding(0);
ここでildasmを使用します...呼び出しが次のように発行されることがわかります。
IL_0002: call class [mscorlib]System.Text.Encoding
[mscorlib]System.Text.Encoding::GetEncoding(int32)
コンパイラが呼び出しを解決しましたEncoding.GetEncoding
-残っている痕跡はありませんUnicodeEncoding
。それはあなたの「現在のタイプ」の考えを無意味なものにします、私は恐れています。
別の解決策は、自己参照型を使用することです
//My base class
//I add a type to my base class use that in the static method to check the type of the caller.
public class Parent<TSelfReferenceType>
{
public static Type GetType()
{
return typeof(TSelfReferenceType);
}
}
次に、それを継承するクラスで、自己参照型を作成します。
public class Child: Parent<Child>
{
}
これで、Parent内の呼び出しタイプtypeof(TSelfReferenceType)は、インスタンスを必要とせずに、呼び出し元のTypeを取得して返します。
Child.GetType();
-ロブ
this
静的メソッドでは使用できないため、これを直接行うことはできません。ただし、オブジェクトのタイプが必要な場合は、それを呼び出しGetType
て、this
インスタンスを渡す必要のあるパラメータにします。たとえば、次のようにします。
public class Car {
public static void Drive(Car c) {
Console.WriteLine("Driving a {0}", c.GetType());
}
}
しかし、これは貧弱なデザインのようです。本当にそれ自体の静的メソッド内にインスタンス自体のタイプを取得する必要があると確信していますか?それは少し奇妙に思えます。インスタンスメソッドを使用しないのはなぜですか?
public class Car {
public void Drive() { // Remove parameter; doesn't need to be static.
Console.WriteLine("Driving a {0}", this.GetType());
}
}
typeof(ThisTypeName)を使用できない理由がわかりません。これが非ジェネリック型である場合、これは機能するはずです。
class Foo {
static void Method1 () {
Type t = typeof (Foo); // Can just hard code this
}
}
ジェネリック型の場合:
class Foo<T> {
static void Method1 () {
Type t = typeof (Foo<T>);
}
}
ここに明らかなものが欠けていますか?
メンバーが静的である場合、実行時にそのメンバーがどの型に属しているかが常にわかります。この場合:
class A
{
public static int GetInt(){}
}
class B : A {}
呼び出すことはできません(編集:どうやら、以下のコメントを見ることができますが、それでもAを呼び出すことになります)。
B.GetInt();
メンバーは静的であるため、継承シナリオには関与しません。エルゴ、あなたはいつもタイプがAであることを知っています。
私の目的では、@ T-motyのアイデアが好きです。「自己参照型」情報を何年も使用してきましたが、基本クラスを参照することは後で行うのが困難です。
たとえば(上記の@Rob Leclercの例を使用):
public class ChildA: Parent<ChildA>
{
}
public class ChildB: Parent<ChildB>
{
}
たとえば、このパターンでの作業は困難な場合があります。関数呼び出しから基本クラスをどのように返しますか?
public Parent<???> GetParent() {}
またはタイプキャストするとき?
var c = (Parent<???>) GetSomeParent();
だから、できる限りそれを避け、必要なときにそれを使うようにしています。必要な場合は、次のパターンに従うことをお勧めします。
class BaseClass
{
// All non-derived class methods goes here...
// For example:
public int Id { get; private set; }
public string Name { get; private set; }
public void Run() {}
}
class BaseClass<TSelfReferenceType> : BaseClass
{
// All derived class methods goes here...
// For example:
public TSelfReferenceType Foo() {}
public void Bar(TSelfRefenceType obj) {}
}
これで(もっと)で簡単に作業できますBaseClass
。ただし、私の現在の状況のように、基本クラス内から派生クラスを公開する必要がない場合もあり、@ M-motyの提案を使用するのが適切な方法かもしれません。
ただし、@ M-motyのコードの使用は、基本クラスのインスタンスコンストラクターがコールスタックに含まれていない場合にのみ機能します。残念ながら、私の基本クラスはインスタンスコンストラクタを使用します。
したがって、基本クラスの「インスタンス」コンストラクターを考慮に入れる私の拡張メソッドは次のとおりです。
public static class TypeExtensions
{
public static Type GetDrivedType(this Type type, int maxSearchDepth = 10)
{
if (maxSearchDepth < 0)
throw new ArgumentOutOfRangeException(nameof(maxSearchDepth), "Must be greater than 0.");
const int skipFrames = 2; // Skip the call to self, skip the call to the static Ctor.
var stack = new StackTrace();
var maxCount = Math.Min(maxSearchDepth + skipFrames + 1, stack.FrameCount);
var frame = skipFrames;
// Skip all the base class 'instance' ctor calls.
//
while (frame < maxCount)
{
var method = stack.GetFrame(frame).GetMethod();
var declaringType = method.DeclaringType;
if (type.IsAssignableFrom(declaringType))
return declaringType;
frame++;
}
return null;
}
}
編集 この方法は、markmnlが指摘したように、実行可能ファイル/ライブラリを含むPDBファイルを展開する場合にのみ機能します。
それ以外の場合は、検出すべき大きな問題になります。開発ではうまく機能しますが、本番環境では機能しない可能性があります。
ユーティリティメソッド。コードのすべての場所から、必要なときにメソッドを呼び出すだけです。
public static Type GetType()
{
var stack = new System.Diagnostics.StackTrace();
if (stack.FrameCount < 2)
return null;
return (stack.GetFrame(1).GetMethod() as System.Reflection.MethodInfo).DeclaringType;
}