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

时间:2012-01-24 22:04:11

标签: c# pointers unsafe

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

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

所以,如果我有:

int MyField;

MyFunction(ref MyField)

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

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

5 个答案:

答案 0 :(得分: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);
    }
}

现在你可以说:

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

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

答案 1 :(得分:6)

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

答案 2 :(得分:2)

ref关键字的使用是明确设计的,以防止代码执行我认为你要求的(即能够有一个函数导致在退出后通过'ref'参数传递的存储位置的修改) 。如果你希望允许代码滥用并传递可修改的引用,可以将它设置为包装器对象中的公共字段,或者实例化单个元素数组并传递它。

答案 3 :(得分:0)

使用Ref parameter传递对MyField的引用

答案 4 :(得分:0)

不....你不能存储参考....

但是你可以将它包装在一个类中并存储对它的引用。