在原始类型的参数中使用C#7.2 in modifier

Dre*_*kes 14 .net c# optimization c#-7.2 in-parameters

C#7.2引入了in修饰符,用于通过引用传递参数,并保证接收者不会修改参数.

这篇文章说:

你永远不应该使用非readonly结构作为in参数,因为它可能会对性能产生负面影响,如果结构是可变的,可能会导致模糊的行为

这是什么意思为内置原语,例如int,double

我想in用来表达代码中的意图,但不是以防御性副本的性能损失为代价.

问题

  • 通过in参数传递原始类型并且没有制作防御性副本是否安全?
  • 是否有其他常用的框架结构,例如DateTime,TimeSpan,Guid,...考虑readonly由JIT?
    • 如果这因平台而异,我们怎样才能找出在特定情况下哪些类型是安全的?

Hei*_*nzi 8

快速测试显示,目前,是的,为内置基元类型和结构创建了防御性副本.

使用VS 2017(.NET 4.5.2,C#7.2,发布版本)编译以下代码:

using System;

class MyClass
{
    public readonly struct Immutable { public readonly int I; public void SomeMethod() { } }
    public struct Mutable { public int I; public void SomeMethod() { } }

    public void Test(Immutable immutable, Mutable mutable, int i, DateTime dateTime)
    {
        InImmutable(immutable);
        InMutable(mutable);
        InInt32(i);
        InDateTime(dateTime);
    }

    void InImmutable(in Immutable x) { x.SomeMethod(); }
    void InMutable(in Mutable x) { x.SomeMethod(); }
    void InInt32(in int x) { x.ToString(); }
    void InDateTime(in DateTime x) { x.ToString(); }

    public static void Main(string[] args) { }
}
Run Code Online (Sandbox Code Playgroud)

使用ILSpy反编译时产生以下结果:

...
private void InImmutable([System.Runtime.CompilerServices.IsReadOnly] [In] ref MyClass.Immutable x)
{
    x.SomeMethod();
}

private void InMutable([System.Runtime.CompilerServices.IsReadOnly] [In] ref MyClass.Mutable x)
{
    MyClass.Mutable mutable = x;
    mutable.SomeMethod();
}

private void InInt32([System.Runtime.CompilerServices.IsReadOnly] [In] ref int x)
{
    int num = x;
    num.ToString();
}

private void InDateTime([System.Runtime.CompilerServices.IsReadOnly] [In] ref DateTime x)
{
    DateTime dateTime = x;
    dateTime.ToString();
}
...
Run Code Online (Sandbox Code Playgroud)

(或者,如果你喜欢IL :)

IL_0000: ldarg.1
IL_0001: ldobj [mscorlib]System.DateTime
IL_0006: stloc.0
IL_0007: ldloca.s 0
IL_0009: call instance string [mscorlib]System.DateTime::ToString()
IL_000e: pop
IL_000f: ret
Run Code Online (Sandbox Code Playgroud)

  • @MikeStrobel:出于表现目的,你是对的.但是,OP希望使用`in`进行文档编制(以证明该值在方法中保持不变),这是一个不同的用例. (3认同)