【问题标题】:C# ref return a ref returnC# ref 返回一个 ref 返回
【发布时间】:2021-09-03 17:22:53
【问题描述】:

我正在尝试创建一个 ref return 方法,该方法返回另一个 ref return 方法,但无法使其工作如果这些方法采用 ref 参数

示例代码如下:

public class TestRef
{
    public int storage=42;


    public ref int Get(ref bool someParam)
    {
        return ref this.storage;
    }

    public ref int Get2(bool someParam)
    {
        var someParam2 = someParam;
        ref var result =ref Get(ref someParam2);

        return ref result;
    }

}

这样做我在底部return ref result; 行看到以下错误: Error CS8157 Cannot return 'result' by reference because it was initialized to a value that cannot be returned by reference

但是这段代码可以工作:

public class TestRef
{
    public int storage=42;


    public ref int Get()
    {
        return ref this.storage;
    }

    public ref int Get2()
    {
        ref var result =ref Get();
        return ref result;
    }

}

我在这里做错了什么?如何通过引用返回结果?

【问题讨论】:

  • Get 实际上并没有改变参数,那么你为什么首先通过 ref 传递它?如果你没有理由就不要这样做。
  • 尽可能简单地提供重现/示例。
  • 强烈考虑是否要变异参数。一般来说,您希望避免副作用。
  • 我没有改变参数。通过 ref 传递是一种性能优化。请不要陷入ref bool someParam 的琐碎程度。这只是问题的一个简单示例。
  • @JasonS 通过引用传递这样的参数可能会使其性能更差,而不是更好。只有在传递的参数很大时才可能对性能有帮助(出于这个原因,您应该尽可能避免这种情况)。如果不传递没有充分理由由 ref 传递的参数可以解决您的问题,那么它已经解决了您的问题。请记住,示例应充分代表实际问题,而不是尽可能简单到掩盖实际问题的程度。

标签: c# .net-6.0 c#-10.0


【解决方案1】:

"ref returns" (C# 7.0) champion 链接到this article,其中列出了下一个“安全返回”规则:

  • 堆上变量的引用可以安全返回
  • ref 参数可以安全返回
  • out 参数可以安全返回(但必须明确指定,就像今天一样)
  • 只要接收方可以安全返回,实例结构字段就可以安全返回
  • “this”从结构成员返回是不安全的
  • 如果作为形式参数传递给该方法的所有 refs/out 都可以安全返回,则从另一个方法返回的 ref 可以安全返回。

您的代码违反了最后一个 - 导致局部变量 someParam2 不能安全返回。要么使 Get 接受 bool someParam 要么使 someParamGet2 ref bool 并删除本地分配(ref var someParam2 = ref someParam; 也可以):

public ref int Get2(ref bool someParam)
{
    ref var result = ref Get(ref someParam);

    return ref result;
}

【讨论】:

  • 我没有投反对票,但我认为这不是一个有效的答案。 someParam2 不返回。 Get2()的返回应该没关系
  • @JasonS 没关系 - 这些被列为确定“安全返回”状态的规则。 someParam2 被传递给 Getref 参数,并且是堆栈上的局部变量,因此返回一个是不安全的。
  • @JasonS 至少部分有意义。想象一下,如果someParamint,那么你可以让Get(ref int i){return ref i;} 这将使Get2(...){int local = 1; return ref Get(ref local);} 做一些非常错误的事情。
  • 好的,谢谢,最后的评论很有道理。我建议您将其添加到您的答案中!我会接受的! (当然还有点赞)
猜你喜欢
  • 2019-12-23
  • 2017-08-10
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 1970-01-01
  • 2020-04-11
  • 2014-05-30
  • 2012-05-28
相关资源
最近更新 更多