Есть ли способ создать ссылку на поле только для чтения в выражениях C#? - PullRequest
0 голосов
/ 08 мая 2020

Я пытаюсь создать MethodCallExpression для метода, который принимает параметр по ссылке (и может изменять этот параметр). Это выражение является частью ExpressionTree, которое позже компилируется в делегат.

Для полей, не предназначенных только для чтения, все работает, как ожидалось, но когда я передаю поле только для чтения, компилятор каким-то образом передает поле по значению и изменение параметра не влияет на поле только для чтения. Объект, из которого поступает поле только для чтения, может быть структурой или объектом.

Как я могу обмануть компилятор, чтобы передать поле только для чтения в качестве фактической ссылки?

Я знаю, что он должен был быть только для чтения, но с отражением вы также можете изменить поле. (даже со структурами: FieldInfo.SetValueDirect(__makeref(...), value))

Пример кода:

internal class Program
{
    private struct Foo
    {
        private readonly int MyInt;

        public Foo(int myInt)
        {
            MyInt = myInt;
        }
    }

    public static void IncrementInt(ref int i)
    {
        i++;
    }

    private delegate void RefAction<T>(ref T parameter);

    private static void Main(string[] args)
    {
        var field = typeof(Foo).GetField("MyInt", BindingFlags.NonPublic | BindingFlags.Instance);
        var method = typeof(Program).GetMethod(nameof(IncrementInt));

        var parameter = Expression.Parameter(typeof(Foo).MakeByRefType());
        var call = Expression.Call(method, Expression.MakeMemberAccess(parameter, field));
        var deleg = Expression.Lambda<RefAction<Foo>>(call, parameter).Compile();

        var foo = new Foo(0);
        deleg(ref foo);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...