c#支持按结果调用吗?

本文关键字:调用 结果 支持 | 更新日期: 2023-09-27 18:12:08

我知道c#中有3种参数求值类型:

  1. 默认值,按值
  2. ref,即by-ref
  3. out,它是通过引用的,但被认为是初始化的,并且强制分配

我的教授说c#也支持by-result,他解释为:

  1. 参数必须与lhs兼容
  2. 创建参数的本地副本并对其进行操作
  3. 方法体处理成功后,将副本的值写回参数源

c#支持按结果调用吗?

简短的回答——不,它没有。

虽然不清楚teacher的意思,但有可能获得在文本上匹配的代码,例如

 int i = 1; f(i); //now i is 2

使用捕获局部变量的lambda表达式。

int i = 1;
Action<int> f = v => i = 2 * v; 
f(i); 
Console.WriteLine(i); // now i is 2

注意i在对f的调用中是严格按值传递的。

也可以是f(42) -参数对执行结果更改的变量没有任何影响。

不,不是c#语言的显式特性。它不会出现主要的混叠问题,当一种语言只支持引用传递或将指针作为一阶语言特性时,混叠问题很常见。除了lock关键字之外,几乎没有语法使线程化更容易。

c#中的一个有用规则是禁止通过引用传递属性,这个问题只能通过call-by-result来解决。值得注意的是VB。NET没有这个规则,它通过自动实现按结果调用来解决这个问题。这确实有制造惊喜的诀窍。

它确实发生在另一个执行上下文中的MarshalByRefObject上。比如另一个AppDomain或另一台机器。因此,必须在调用之前跨上下文边界复制ref参数,然后再复制回来。然而,这在很大程度上对程序是透明的,不包括需要显式应用[Out]属性的怪癖。

我想你的教授可能指的是方法完成后的简单变量重新赋值(即i = DoSomething(i)),或者可能是在后台导致变量重新赋值的运算符,即++

为了说明这一点:

class Immutable
{
    public readonly int Value;
    public Immutable(int value)
    {
        this.Value = value;
    }
    public static Immutable operator ++(Immutable obj)
    {
        return new Immutable(obj.Value + 1);
    }
}

现在我们可以做以下操作:

Immutable a = new Immutable(1);
Immutable originalA = a;
Debug.Assert(a.Value == 1);
Debug.Assert(a == originalA); // Same instance (obviously).
a++;
Debug.Assert(a.Value == 2);
Debug.Assert(a != originalA); // New instance.

这似乎满足所有条件:

  • 可以Immutable类型的变量执行LHS赋值。
  • operator方法接收到原始变量的副本(你可以在方法体中重新分配obj,它不会影响原始位置)。
  • a在操作符完成执行后被重新分配,并将指向新创建的实例。

编辑

虽然这绝对不是答案,因为它不满足任何点,我认为值得一提的是,你也可以通过传递指针来获得"by ref"语义,我相信每个人都知道。然而,有些人可能不知道的是,这也可以使用TypedReference来完成,这是MS c#中的一个特殊野兽:

void DodgyIncrement()
{
    int i = 0;
    this.Increment(__makeref(i));
    Debug.Assert(i == 1);
}
void Increment(TypedReference i)
{
    __refvalue(i, int) += 1;
}