Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.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
C# 关于在C中哪些类型的对象可以“通过引用返回”的问题_C#_Ref - Fatal编程技术网

C# 关于在C中哪些类型的对象可以“通过引用返回”的问题

C# 关于在C中哪些类型的对象可以“通过引用返回”的问题,c#,ref,C#,Ref,我在看书。 至于通过引用返回,它说 由于对象生命周期的原因,按引用返回有两个重要的限制:对象引用在仍被引用时不应被垃圾收集,当它们不再有任何引用时不应消耗内存。要强制执行这些限制,只能从引用返回函数返回以下内容: •对字段或数组元素的引用 •其他参考返回属性或功能 •作为参数传入by reference返回函数的引用 我做了一些实验,结果肯定如书中所说 namespace App { public class App { static void Main()

我在看书。 至于通过引用返回,它说

由于对象生命周期的原因,按引用返回有两个重要的限制:对象引用在仍被引用时不应被垃圾收集,当它们不再有任何引用时不应消耗内存。要强制执行这些限制,只能从引用返回函数返回以下内容: •对字段或数组元素的引用 •其他参考返回属性或功能 •作为参数传入by reference返回函数的引用

我做了一些实验,结果肯定如书中所说

namespace App
{
    public class App
    {
        static void Main()
        {

        }
        class Test
        {
            public int x;
        }
        ref int RefReturn()
        {
            int[] a = { 1, 2 };
            return ref a[0];
        }
        ref int RefReturn2()
        {
            Test t = new Test();
            return ref t.x;
        }
        ref int RefReturnError()
        {
            int a = 1;
            return ref a; //Error
        }
        ref Test RefReturnError2()
        {
            Test t = new Test();
            return ref t; //Error
        }
    }
}
我不太明白这一点。 这三种可以在书中引用,为什么这三种? 例如,我可以返回类的字段,但不能返回类。 代码中的ref int RefReturn2和ref Test RefReturnError2

我认为应该是关于C中的对象生命周期和垃圾收集的问题,我对此不太了解

我还想知道使用参照退货的典型情况。
我认为典型情况也有助于理解。

局部变量与方法具有相同的生存期,变量本身的内存位置在堆栈上

因此,在方法返回后,变量int a或Test t都不存在

但是[0]和t.x存在于存储在堆内存中的对象中。当方法返回时,它们仍然存在,因为它们位于堆栈之外

举个例子吧。为什么use希望使用ref local或ref return?定义链表时如何

内部类节点 T:在哪里上课 { 内部T项目; 内部节点下一步; } 公共类链接列表 T:在哪里上课 { 私有节点根; 私有ref节点FindFunc比较 { ref var ret=参考根; 而ret!=null&&comparisonret.Item ret=参考ret.Next; 返回ref ret; } public void InsertT newItem,Func比较 { ref var位置=ref Findcomparison; 位置=新节点 { Item=newItem, 下一个=位置。下一个 }; } } Find返回对节点字段的引用,然后可以将新节点分配给该字段。因此,您可以处理分配给根或某个节点的操作。接下来,无需两种特殊情况。

托管引用规则ref的关键要点是:托管引用不能指向局部变量,或者在结构的情况下不能指向局部变量的一部分,因为该引用可以超过其指向的位置的寿命。它必须指向非堆栈位置

让我们一个接一个地看每个版本

ref int RefReturn { int[]a={1,2}; 返回参考a[0]; } 在上面的示例中,返回的引用指向数组的内部,而不是指向局部变量。数组的内部实际上是堆对象的字段。数组将超过函数的生命周期

ref int RefReturn2 { 试验t=新试验; 返回参考t.x; } 在本例中,Test是引用类型,因此存在于堆中。引用指向t中包含的对象的字段x,它也存在于堆中。t是局部变量这一事实无关紧要,参考文献并不指向t

ref int RefReturnError { INTA=1; 返回ref a;//错误 } 在这种情况下,引用指向局部变量的实际位置,该位置位于堆栈上,并且该位置将在函数结束时消失

请注意,当引用结构的字段时,当结构的位置是局部变量时,同样的问题也会出现

参考int RefReturnError1A { MyStruct a=新MyStruct; 返回ref a.x;//错误 } 参考测试RefReturnError2 { 试验t=新试验; 返回ref t;//错误 } 在本例中,尽管t是一个引用类型,并且它本身指向一个堆对象,但我们的引用并没有指向t所指向的对象。它指向包含该对象引用的t本身的位置

请注意,由于不同的原因,不允许引用已装箱的结构:由于C的取消装箱规则,从逻辑上来说,取消装箱将创建一个副本,因此您无法就地更改它。直接在IL或C++/CLI中编码您可以完全验证地执行以下等效操作:

ref int RefReturnBox { 对象a=对象1; return ref inta;//CS0445:无法修改取消装箱转换的结果 }
你到底不明白什么?你所说的“不上课”是什么意思?你是指代码中的某一行吗?你到底指的是什么
你明白吗我不明白这本书的意思,这三种可以通过引用返回。这很难记住。这本书说这是关于对象生命周期的,但我不明白为什么。我想从RefReturn2工作的原因开始,但RefReturnError2失败了。我不使用Ref返回和Ref局部变量,因为我相信它会产生复杂的代码;但同时,我会对这两种方法的不同感兴趣。你说的“但不是”类是什么意思?您是指代码中的特定行吗?-是的,我指的是代码中的ref int RefReturn2和ref Test RefReturnError2函数。meh-我不喜欢这个答案,因为它没有解释RefReturnError2是如何工作的。测试t在堆上。它不是值类型。就像在RefReturn2中一样。@Andy否,只有t存储引用的测试对象在堆上。如果您希望通过引用返回该测试对象,则返回t;做返回参考t;如果有效,将通过引用返回局部变量t。封闭方法返回后,局部变量不存在。回答得好。快速提问-最后一句:它指向t的位置-你的话存储在堆栈上,对吗?这就是为什么它不能工作,因为堆栈在返回时被销毁。正确,t的位置不是t指向的对象存在于堆栈上