Можно ли отследить присваивание результата выполнения метода?

Условно есть MyLib1.dll в которой есть следующий метод:

public static int Sum(int a, int b)
{
   return a + b;
}

Так же есть какой-то юзер моей библиотеки который вызывает этот метод. Могу ли я отследить присваивание значения которое вернет мой метод?

Т.е условно это выглядит так (в юзерском коде):

int result = MyLib.LibClass.Sum(5, 5);

После выполнения этого метода выделяется (возможно нет, но не суть) память под result, и в своей MyLib1.dll я хочу узнать было ли присваивание значения. Как это можно реализовать и можно ли вообще?


Ответы (2 шт):

Автор решения: Alexander Petrov

Ладно, напишу.
Допустим, что в этой теме мы обсуждаем всякое странное!

Используем Ref returns and ref locals.

В метод добавим ключевое слово ref в сигнатуру и в место возврата:

namespace MyLib
{
    public static class LibClass
    {
        static int c;

        public static ref int Sum(int a, int b)
        {
            c = a + b;
            return ref c;
        }
    }
}

Теперь, если при вызове тоже использовать ref, переменная будет ссылаться на память, выделенную для поля c.

ref int x = ref MyLib.LibClass.Sum(5, 5);
Console.WriteLine(x);

ref int y = ref MyLib.LibClass.Sum(5, 6);
Console.WriteLine(x);
Console.WriteLine(y);

Это выведет:

10
11
11

Видно, что значение x поменялось при втором вызове.

А если не использовать ref:

int a = MyLib.LibClass.Sum(5, 5);
Console.WriteLine(a);

int b = MyLib.LibClass.Sum(5, 6);
Console.WriteLine(a);
Console.WriteLine(b);

будет вывод:

10
10
11

В этом варианте значение a остаётся прежним.


Не знаю, зачём всё это. Ну а вдруг!

→ Ссылка
Автор решения: Alexander Petrov

Можно использовать операторы преобразования. User-defined conversion operators.

namespace MyLib
{
    public readonly struct MyNumber
    {
        private readonly int _number;

        public MyNumber(int number) => _number = number;

        public static implicit operator int(MyNumber number)
        {
            Console.WriteLine("присваивание");
            return number._number;
        }
        public static implicit operator MyNumber(int number)
        {
            Console.WriteLine("вызов");
            return new MyNumber(number);
        }

        public override string ToString() => _number.ToString();
    }

    public static class LibClass
    {
        public static MyNumber Sum(int a, int b)
        {
            return a + b;
        }
    }
}

Перегружены операторы присваивания. В них мы можем вставить код, реагирующий на их вызов.

Я оба оператора сделал неявными (implicit), что не рекомендуется. Но для наших целей сойдёт.


Пробуем:

int x = MyLib.LibClass.Sum(5, 5);

Выдаст

вызов
присваивание

То есть можно узнать, было ли присваивание!


Если написать

MyLib.LibClass.Sum(5, 5);

Результат будет

вызов

Присваивания нет!


Однако, если написать

var y = MyLib.LibClass.Sum(5, 5);

или, что равноценно

MyNumber z = MyLib.LibClass.Sum(5, 5);

Результат

вызов

То есть о присваивании в этом случае мы не узнаем.

→ Ссылка