在C#中,有没有办法模拟传递指针(不使用unsafe关键字)

Tho*_*mas 0 c# pointers unsafe

如果不使用'Unsafe'关键字,可以完成以下操作:

将字段作为参数传递给函数.该函数可以定期更改该字段的值.

所以,如果我有:

int MyField;
Run Code Online (Sandbox Code Playgroud)

和:

MyFunction(ref MyField)
Run Code Online (Sandbox Code Playgroud)

该函数可以存储指针MyField并根据需要更改其值.

在C++中,我们只是传递一个指向该值的指针,然后根据需要进行更改,但我试图找出是否可以在C#中完成.我猜它可以通过反思来完成.

Eri*_*ert 10

让我重新解释一下这个问题:

我可以将对变量的引用作为参数传递给存储引用的方法,以便我的代码可以在以后更新变量吗?

没有.

在CLR类型系统中,对变量的引用可以作为形式参数传递.它们也可以从方法调用返回存储在已知寿命较短的局部变量中.(C#不支持后两个功能;有关详细信息,请参阅我关于该主题的文章:http://blogs.msdn.com/b/ericlippert/archive/2011/06/23/ref-returns-and-ref-locals .aspx.)

但是,它们不能存储在字段或数组中.简而言之,对变量的引用可能只存储在已知为短暂的位置.

这种限制的原因是因为你不能同时拥有所有这四种理想的品质:

  • 任何变量都可以通过引用传递
  • 访问变量的引用总是安全的(在安全代码中;如果变量是指向不安全代码的指针,则负责确保其安全性,而不是运行时.)
  • 可以在没有垃圾收集的情况下清除短期变量(即,通过"弹出堆栈"或重用寄存器,或者使用其他任何非基于非gc的存储回收系统用于短期存储池.)
  • 变量引用可以存储在长期存储位置中

其中一个必须给予,CLR设计师选择最后一个作为丢失的那个.C和C++的设计者选择了第二个作为失败者.

我猜它可以通过反思来完成.

这不可以.但是可以与代表们一起完成.

class C
{
    private Action<int> setter;
    public void RecordSetter(Action<int> setter)
    {
        this.setter = setter;
    }
    public void SetIt(int x)
    {
        this.setter(x);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以说:

class D
{
    int myField;
    void M()
    {
        C c = new C();
        c.RecordSetter(x=>{myField = x; });
        c.SetIt(123);
        Console.WriteLine(myField);
    }
}
Run Code Online (Sandbox Code Playgroud)

只要C的实例保持活动状态,垃圾收集器就会确保D的实例保持活动状态.


Jus*_*ner 6

你实际上是通过使用引用参数(你传递一个引用......指针......而不是值本身)来做到这一点.