Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么';t C#支持返回参考资料?_C#_.net_Reference_Return Type - Fatal编程技术网

为什么';t C#支持返回参考资料?

为什么';t C#支持返回参考资料?,c#,.net,reference,return-type,C#,.net,Reference,Return Type,我曾读到.NET支持返回引用,但C#不支持。有什么特别的原因吗?为什么我不能做这样的事情: static ref int Max(ref int x, ref int y) { if (x > y) return ref x; else return ref y; } public delegate void MyByRefConsumer<T>(ref T val); public void DoSomethingWithValueT

我曾读到.NET支持返回引用,但C#不支持。有什么特别的原因吗?为什么我不能做这样的事情:

static ref int Max(ref int x, ref int y) 
{ 
  if (x > y) 
    return ref x; 
  else 
    return ref y; 
} 
public delegate void MyByRefConsumer<T>(ref T val);

public void DoSomethingWithValueType(MyByRefConsumer<int> c)
{
        int x = 2;
        c(ref x);
        //Handle potentially changed x...
}

您正在讨论返回对值类型的引用的方法。我所知道的C#中唯一的内置示例是值类型的数组访问器:

public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}
现在创建该结构的数组:

var points = new Point[10];
points[0].X = 1;
points[0].Y = 2;
在本例中,
点[0]
,数组索引器将返回对结构的引用。不可能编写具有相同“返回引用”行为的自己的索引器(例如,对于自定义集合)


我没有设计C语言,所以我不知道不支持它背后的所有理由,但我认为简短的答案可能是:没有它,我们可以相处得很好。

这个问题是我们讨论的主题。谢谢你的提问

C#团队正在为C#7考虑这一点。有关详细信息,请参阅

更新:该功能进入C#7


你说得对。NET不支持返回变量托管引用的方法。NET还支持包含对其他变量的托管引用的局部变量。(但是请注意,.NET不支持包含对其他变量的托管引用的字段数组,因为这会使垃圾收集故事过于复杂。还有“对变量的托管引用”类型不能转换为对象,因此不能用作泛型类型或方法的类型参数。)

评论员“RPM1984”出于某种原因要求引用这一事实。RPM1984我建议您阅读CLI规范分区I第8.2.1.1节“托管指针和相关类型”,以了解有关.NET此功能的信息

完全可以创建一个同时支持这两种功能的C#版本。然后你可以做类似的事情

static ref int Max(ref int x, ref int y) 
{ 
  if (x > y) 
    return ref x; 
  else 
    return ref y; 
} 
然后用你的名字来称呼它

int a = 123;
int b = 456; 
ref int c = ref Max(ref a, ref b); 
c += 100;
Console.WriteLine(b); // 556!
根据经验,我知道构建一个支持这些特性的C#版本是可能的,因为我已经这样做了。高级程序员,特别是人们移植非托管C++代码,经常要求我们使用C++之类的能力来做引用的事情,而不必拿出实际使用指针和钉住内存的大锤子。通过使用托管引用,您可以获得这些好处,而无需付出提高垃圾收集性能的代价

我们已经考虑过这个特性,并且实际实现了足够多的特性,可以向其他内部团队展示,以获得他们的反馈。然而,根据我们的研究,目前我们认为该功能没有足够广泛的吸引力或令人信服的使用案例使其成为真正受支持的语言功能。我们还有其他更高的优先级和有限的时间和精力,所以我们不会很快完成这个功能

此外,正确地执行此操作需要对CLR进行一些更改。目前,CLR将ref返回方法视为合法但无法验证的方法,因为我们没有检测这种情况的检测器:

ref int M1(ref int x)
{
    return ref x;
}

ref int M2()
{
    int y = 123;
    return ref M1(ref y); // Trouble!
}

int M3()
{
    ref int z = ref M2();
    return z;
}
M3返回M2局部变量的内容,但该变量的生存期已结束!可以编写一个检测器来确定ref返回的使用,该返回显然不会违反堆栈安全。我们要做的是编写这样一个检测器,如果检测器不能证明堆栈的安全性,那么我们就不允许在程序的这一部分使用ref返回。要做到这一点,开发人员的工作量并不大,但要确保我们真正掌握了所有案例,测试团队的负担很大。这只是另一件事,它增加了功能的成本,以至于现在的好处并不超过成本

如果您能为我描述一下您为什么需要此功能,我将非常感激。我们从真正的客户那里获得的关于他们为什么需要它的信息越多,将来它就越有可能被应用到产品中。这是一个可爱的小功能,如果有足够的兴趣,我希望能够以某种方式将其提供给客户


(另请参见相关问题和)

您可以随时执行以下操作:

static ref int Max(ref int x, ref int y) 
{ 
  if (x > y) 
    return ref x; 
  else 
    return ref y; 
} 
public delegate void MyByRefConsumer<T>(ref T val);

public void DoSomethingWithValueType(MyByRefConsumer<int> c)
{
        int x = 2;
        c(ref x);
        //Handle potentially changed x...
}
公共委托无效MyByRefConsumer(ref T val);
public void DoSomethingWithValueType(MyByRefC)
{
int x=2;
c(参考文献x);
//处理可能更改的x。。。
}

C#7.0支持返回引用。看看我的答案。

嗯……请引用?C有值和引用类型,都可以返回。你的意思是什么。我说的是
返回ref x
四年后,你可以用
C#7
:)来做这件事。Tom问的是返回变量引用的方法。变量不必是值类型,当然这通常是人们在需要ref返回方法时想要的。否则,就需要进行大量的分析;正确的是,在C语言中,复杂表达式生成变量引用的唯一地方是数组索引器,用户随后可以操作该变量。(当然还有成员访问操作符“.”在接收器和字段之间,但这显然是对变量的访问。)@EricLippert:我没有令人信服的例子,这只是我想知道的。优秀而引人注目response@Eric:在您的示例中,从
M2
返回后保持
y
处于活动状态不是更合适吗?我希望这个功能可以像lambdas捕捉本地人一样工作。或者您提出的行为是因为CLR是如何处理该场景的?@Eric:IMHO在.net语言中,让属性返回对值类型的引用的功能是一个重大遗漏。如果Arr是一个值类型的数组(例如点),可以说例如Arr(3).X=9,并且知道没有更改Arr(9).X的值,甚至没有更改其他数组(2).X的值;如果Arr是ins