Допустим, есть класс, который вызывает в методе конструктор и создает тип.
Можно ли неявно в конструкторе класса получить ссылку на класс без явной передачи this
в конструктор?
Пример:
public class A
{
public void MethodA()
{
var b = new B();
}
}
public class B
{
public B()
{
// каким-то образом неявно получаем ссылку на класс, который вызвал конструктор.
// Т.е в данном случае ссылка на экземпляр A
}
}
Если не ошибаюсь, то в IL
в качестве первого аргумента всегда неявно передается ссылка на вызывающий код.
P.S Задач никаких нету. Интереса ради.
Нет, вы не можете получить экземпляр вызывающего класса. Этой информации нету даже на уровне IL. Конструктор B
, декомпилированный в ILDasm, выглядит так:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Размер кода: 9 (0x9)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ret
} // end of method B::.ctor
У него нету объявления параметров, так что скрытых параметров нету.
То, что вы можете выяснить — это какой конкретно метод вас вызывает, без указания на экземпляр класса. Это делается так:
[MethodImpl(MethodImplOptions.NoInlining)]
public B()
{
MethodBase callingMethod = new StackFrame(1).GetMethod();
Console.WriteLine($"Called from type: {callingMethod.DeclaringType.FullName}, " +
$"calling method name: {callingMethod.Name}");
}
У меня выводит:
Called from type: Test.A, calling method name: MethodA
Вы создаёте stack frame, начинающийся на 1 выше вашего текущего фрейма, и запрашиваете метод. Имея reflection-дескриптор метода, вы можете получить информацию из него.
Заметьте, что я применил атрибут MethodImplOptions.NoInlining
, чтобы запретить встраивать этот метод в точку вызова, в противном случае в stack trace могла бы попасть не та информация.
Ещё один немаловажный момент: запрос StackFrame
— затратная, дорогостоящая операция, поэтому не стоит применять это решение в production-коде. Если вы хотите информацию о том. кто вас вызвал, в production-коде, стоит доверить это компилятору и воспользоваться атрибутом [CallerMemberName]
, доступным начиная с .NET 4.5:
public B([CallerMemberName] string callerName = null,
[CallerFilePath] string callerFile = null,
[CallerLineNumber] int callerLineNumber = -1)
{
Console.WriteLine($"Called from method: {callerName}, " +
$"located {callerFile}@{callerLineNumber}");
}
Выводит:
Called from method: MethodA, located D:\full path here\Test\Program.cs@42
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
На главной форме есть элемент panel в нее подгружается "пользовательский элемент управления", при развертывании окна на весь экран элементы...
Пытаюсь поменять тип колонки из числового на строчный но не получаетсяВ чем может быть проблема ?
Здравствуйте, я только начинаю погружаться в мир разработки, хотелось спросить совета, как можно улучшить следующий код:
Есть 3 сущности - репетитор, студент, группа, все связаны друг с другом через многие ко многимРешил сделать так: объявляю статическую переменную...