是否可以在C#中返回对变量的引用?

时间:2010-12-27 23:17:05

标签: c# reference return-value

我可以返回对double值的引用吗?

这就是我想要做的事情:

ref double GetElement()
{
   ......
   // Calculate x,y,z
   return ref doubleArray[x,y,z];
}

像这样使用

void func()
{
   GetElement()=5.0;
}

就像在C ++中返回一个双指针一样...... 我知道我写它的方式是错误的......但有没有正确的方法呢?

5 个答案:

答案 0 :(得分:43)

更新:C#7现在支持所需的功能。


CLR类型系统支持ref-returns方法,我编写了一个C#编译器的实验原型,它支持你想要的功能。 (原型还实现了ref-typed局部变量,但ref-typed字段在CLR类型系统中是非法的。)

你已经完全按照我为原型选择的语法,这意味着无论是伟大的思想是否相同,或者傻瓜永远不会有所不同。

虽然原型工作得非常好,但这不太可能使条形成为下一版C#语言的功能。很少有客户想要这个功能,实现起来相当昂贵,只要您拥有更重要的功能,我们就有一个列表,并且还有其他方法可以使这种事情发挥作用而不会在类型系统中增加这种复杂性。这些都是执行该功能的巨大“点”。

例如,您可以创建一对代表:

struct Ref<T>
{
    private readonly Func<T> getter;
    private readonly Action<T> setter;
    public Ref(Func<T> getter, Action<T> setter)
    {
        this.getter = getter;
        this.setter = setter;
    }
    public T Value { get { return getter(); } set { setter(value); } }
}

var arr = new int[10];
var myref = new Ref<int>(()=>arr[1], x=>arr[1]=x);
myref.Value = 10;
Console.WriteLine(myref.Value);

这比使用ref返回实现的相同功能慢得多,但好处是您可以在ref不合法的地方创建Ref<T>。例如,您可以将Ref<T>存储在字段中,而使用ref-returns方法则无法执行此操作。

如果你有一个非常棒的令人信服的场景,为什么你需要 ref-returns方法,我会来听取它。我们拥有的现实场景越多,这种功能就越有可能在假设的未来版本的语言中实现。

另见相关问题:

Can I use a reference inside a C# function like C++?

Why doesn't C# support the return of references?

和我关于这个主题的博客文章:

http://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/

答案 1 :(得分:8)

不,这在C#中是不可能的。您只能通过引用传递参数。

但是,您可以使用属性获得相同的结果:

double Element
{
    get { return doubleArray[x,y,z]; }
    set { doubleArray[x,y,z] = value; }
}

void func()
{
   Element = 5.0;
}

答案 2 :(得分:6)

可以unsafe code中执行此操作,并且有一个方法可以返回指向double的指针:

unsafe double* GetElementP(){
...
}

答案 3 :(得分:6)

C#中的值类型总是按值传递。对象始终按值传递其引用。正如Axarydax指出的那样,这会改变“不安全”的代码。

避免此约束的最简单,最安全的方法是确保您的double以某种方式附加到对象。

public class MyObjectWithADouble {
    public double Element {get; set;} // property is optional, but preferred.
}

...
var obj = new MyObjectWithADouble();
obj.Element = 5.0

我还想说一下,我对你如何预期将双重赋值给一个三维数组感到困惑。您可能想澄清一下您的目标。

我想我现在更了解你的目标。您希望返回给定数组中值的位置,然后能够更改该位置中的值。这种模式破坏了C#的一些预期范例,因此我建议考虑其他方法来实现您正在寻找的东西。但如果它真的有意义,我会做更多这样的事情:

public class 3dArrayLocation {public int X; public int Y; public int Z;}

...

public 3dArrayLocation GetElementLocation(...)
{
    // calculate x, y, and z
    return new 3dArrayLocation {X = x, Y = y, Z = z}
}

...

var location = GetElementLocation(...);
doubleArray[location.X, location.Y, location.Z] = 5.0;

答案 4 :(得分:1)

经过一番思考,为什么不发送使用这样的函数设置的值:

void SetElement(double value)
{
   ......
   // Calculate x,y,z
   doubleArray[x,y,z]=value;
}

并使用它:

void func()
{
   SetElement(5.0);
}

但是,我仍然会选择一个有用的答案......