비 정적 메서드에서 사용할 수 this.GetType()
있으며 Type
. Type
정적 메서드에서 어떻게 똑같이 얻을 수 있습니까? 물론 런타임에서만 알려져 typeof(ThisTypeName)
있기 때문에 그냥 쓸 수는 없습니다 ThisTypeName
. 감사!
비 정적 메서드에서 사용할 수 this.GetType()
있으며 Type
. Type
정적 메서드에서 어떻게 똑같이 얻을 수 있습니까? 물론 런타임에서만 알려져 typeof(ThisTypeName)
있기 때문에 그냥 쓸 수는 없습니다 ThisTypeName
. 감사!
답변:
this.GetType()
정적 메서드에 해당하는 1 라이너를 찾고 있다면 다음을 시도하십시오.
Type t = MethodBase.GetCurrentMethod().DeclaringType
.NET을 사용하는 것보다 훨씬 비쌉니다 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)는 인스턴스 없이도 호출자의 유형을 가져와 반환합니다.
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();
멤버가 정적이기 때문에 상속 시나리오에서 역할을하지 않습니다. Ergo, 당신은 항상 유형이 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;
}