是否有必要将“in”修饰符与readonly结构一起使用?

时间:2018-05-18 03:27:54

标签: c#

在C#7.2中,readonly结构总是传递给函数,好像“in”参数存在一样?如果没有,在什么情况下复制内存是有用的,只要它是只读的?

我有一个只读结构:

public readonly struct Vec2 
{
     public readonly double X;
     public readonly double Y;
}

当被调用数十亿次时,这两种方法之间会有性能差异:

public double Magnitude1(Vec2 v)
{
    return Math.Sqrt(v.X*v.X + v.Y*v.Y);
}
public double Magnitude2(in Vec2 v)
{
    return Math.Sqrt(v.X*v.X + v.Y*v.Y);
}

如果是这样,为什么编译器不会认识到Vec2是一个只读结构而只是传递它就好像“in”存在一样?是否有一个实例,您可能希望在没有“in”修饰符的情况下传递只读结构?

1 个答案:

答案 0 :(得分:7)

  

readonly结构总是传递给函数,好像" in"参数是否存在?

没有。如果没有in修饰符,readonly结构将按值传递,而不是通过引用传递。

  

如果没有,在什么情况下复制内存会有用呢?

如果您想保证内存没有变化,复制内存会很有用。请记住,结构即使是readonly也可以更改。例如:

readonly struct S
{
    public readonly int I;

    public S(int i) { this.I = i; }
}

class Program
{
    static S s1 = new S(1);

    static void Main()
    {
        A(s1);
    }

    static void A(in S s2)
    {
        Console.Write(s2.I);
        s1 = new S(2); // This is legal even though S is readonly!
        Console.Write(s2.I);
    }
}

使用参数in上的s2修饰符,输出为12.如果没有in修饰符,则输出为11.

这种行为差异意味着编译器无法将in修饰符透明地添加到readonly struct个参数中。 (即使方法A没有修改s1,另一个线程也可以。)

  

当被调用数十亿次时,这两种方法之间会有性能差异吗?

可能有;衡量并看到。我期望结构越大,通过值越慢。

  

如果是这样,为什么编译器不会认识到Vec2是一个只读结构而只是传递它,好像"在"在场?是否存在一个实例,您可能希望在没有" in"的情况下传递readonly结构。改性剂?

也许如果struct非常小(例如,8字节或更少),传递值(例如,在CPU寄存器中)可能比通过引用传递更便宜(然后必须取消引用指针)