Я пытаюсь создать 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);
}
}