gpt4 book ai didi

c# - 使用 Expression> 使值类型表现为引用类型

转载 作者:行者123 更新时间:2023-11-30 15:47:21 26 4
gpt4 key购买 nike

我们知道 int 是一种值类型,因此以下内容是有道理的:

int x = 3;
int y = x;
y = 5;
Console.WriteLine(x); //says 3.

现在,由于缺少更好的术语,我们想要将两个变量“链接”到相同的内存位置,这是一些代码。

int x = 3;
var y = MagicUtilClass.linkVariable(() => x);
y.Value = 5;
Console.WriteLine(x) //says 5.

问题是:方法 linkVariable 是什么样子的?它的返回类型是什么样的?

尽管我将帖子命名为使值类型表现为引用类型,但上述 linkVariable 方法也适用于引用类型......,即,

Person x = new Person { Name = "Foo" };
var y = MagicUtilClass.linkVariable(() => x);
y.Value = new Person { Name = "Bar" };
Console.WriteLine(x.Name) //says Bar.

我不确定如何在 C# 中实现这一点(顺便说一句,不允许使用不安全的代码)?

欣赏创意。谢谢。

最佳答案

这是一个完整的解决方案:

// Credits to digEmAll for the following code
public delegate void Setter<T>(T newValue);
public delegate T Getter<T>();
public class MagicPointer<T>
{
private Getter<T> getter;
private Setter<T> setter;

public T Value
{
get { return getter(); }
set { setter(value); }
}

public MagicPointer(Getter<T> getter, Setter<T> setter)
{
this.getter = getter;
this.setter = setter;
}
}

// Code starting from here is mine
public static class MagicUtilClass
{
public static MagicPointer<T> LinkVariable<T>(Expression<Func<T>> expression)
{
var memberExpr = expression.Body as MemberExpression;
if (memberExpr == null)
throw new InvalidOperationException("The body of the expression is expected to be a member-access expression.");
var field = memberExpr.Member as FieldInfo;
if (field == null)
throw new InvalidOperationException("The body of the expression is expected to be a member-access expression that accesses a field.");
var constant = memberExpr.Expression as ConstantExpression;
if (constant == null)
throw new InvalidOperationException("The body of the expression is expected to be a member-access expression that accesses a field on a constant expression.");
return new MagicPointer<T>(() => (T) field.GetValue(constant.Value),
x => field.SetValue(constant.Value, x));
}
}

用法:

int x = 47;
var magic = MagicUtilClass.LinkVariable(() => x);
magic.Value = 48;
Console.WriteLine(x); // Outputs 48

要了解此解决方案为何有效,您需要知道每当您在 lambda 表达式中使用变量时,编译器都会相当大地转换您的代码(无论该 lambda 表达式是成为委托(delegate)还是表达式树)。它实际上生成了一个包含字段的新类。变量 x 被删除并替换为该字段。用法示例将如下所示:

CompilerGeneratedClass1 locals = new CompilerGeneratedClass1();
locals.x = 47;
var magic = MagicUtilClass.LinkVariable(() => locals.x);
// etc.

代码检索的“字段”是包含x 的字段,它检索的“常量”是locals 实例。

关于c# - 使用 Expression<Func<T>> 使值类型表现为引用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3653854/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com