在修饰符中使用C#7.2处理具有原始类型的参数 [英] Using C# 7.2 in modifier for parameters with primitive types

查看:75
本文介绍了在修饰符中使用C#7.2处理具有原始类型的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

C# 7.2 introduced the in modifier for passing arguments by reference with the guarantee that the recipient will not modify the parameter.

永远不要使用非只读结构作为in参数,因为它可能会对性能产生负面影响,并且如果该结构是可变的,则可能导致晦涩的行为

You should never use a non-readonly struct as the in parameters because it may negatively affect performance and could lead to an obscure behavior if the struct is mutable

这对于诸如intdouble的内置基元意味着什么?

What does this mean for built-in primitives such as int, double?

我想使用in在代码中表达意图,但不以牺牲防御性副本的性能为代价.

I would like to use in to express intent in code, but not at the cost of performance losses to defensive copies.

问题

  • 通过in参数传递基本类型并且没有制作防御性副本是否安全?
  • JIT是否将其他常用框架结构(例如DateTimeTimeSpanGuid,...)视为readonly?
    • 如果具体情况因平台而异,我们如何找出在给定情况下哪种类型是安全的?
    • Is it safe to pass primitive types via in arguments and not have defensive copies made?
    • Are other commonly used framework structs such as DateTime, TimeSpan, Guid, ... considered readonly by the JIT?
      • If this varies by platform, how can we find out which types are safe in a given situation?

      推荐答案

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

      A quick test shows that, currently, yes, a defensive copy is created for built-in primitive types and structs.

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

      Compiling the following code with VS 2017 (.NET 4.5.2, C# 7.2, release build):

      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) { }
      }
      

      使用ILSpy反编译时,

      产生以下结果:

      yields the following result when decompiled with 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();
      }
      ...
      

      (或者,如果您更喜欢IL:)

      (or, if you prefer 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
      

      这篇关于在修饰符中使用C#7.2处理具有原始类型的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆