燕十八html教程网站建设,广东app开发公司,电商运营基本常识,做文献的ppt模板下载网站本文内容 通过引用传递和返回引用安全上下文安全的上下文和 ref 结构统一内存类型通过参考安全提高性能 本节中介绍的技术可提高应用于代码中的热路径时的性能。热路径是代码库中在正常操作中经常重复执行的部分。将这些技术应用于不经常执行的代码将产生最小的影响。在进行任何… 本文内容 通过引用传递和返回引用安全上下文安全的上下文和 ref 结构统一内存类型通过参考安全提高性能 本节中介绍的技术可提高应用于代码中的热路径时的性能。热路径是代码库中在正常操作中经常重复执行的部分。将这些技术应用于不经常执行的代码将产生最小的影响。在进行任何更改以提高性能之前测量基线至关重要。然后分析该基线以确定内存瓶颈发生的位置。 测量内存使用情况并确定可以减少分配后请使用本节中的技术来减少分配。每次连续更改后再次测量内存使用情况。确保每个更改都会对应用程序中的内存使用产生积极影响。 .NET 中的性能工作通常意味着从代码中删除分配。您分配的每个内存块最终都必须被释放。较少的分配可减少垃圾回收所花费的时间。它通过从特定代码路径中删除垃圾回收允许更可预测的执行时间。 减少分配的常用策略是将关键数据结构从类型更改为类型。此更改会影响使用这些类型的语义。参数和返回现在按值传递而不是按引用传递。如果类型很小只有三个字或更少考虑到一个字的自然大小为一个整数则复制值的成本可以忽略不计。它是可衡量的可以对较大的类型产生真正的性能影响。为了消除复制的影响开发人员可以传递这些类型来获取预期的语义。 使用 C# 功能您可以表达所需的类型语义而不会对其整体可用性产生负面影响。在实现这些增强功能之前开发人员需要求助于具有指针和原始内存的构造以实现相同的性能影响。编译器为新的相关功能生成可验证的安全代码。可验证的安全代码意味着编译器检测到可能的缓冲区溢出或访问未分配或释放的内存。编译器会检测并防止某些错误。 1、通过引用传递和返回 C# 中的变量存储值。在类型中该值是该类型的实例的内容。在类型中该值是对存储该类型实例的内存块的引用。添加修饰符意味着变量存储对值的引用。在类型中引用指向包含该值的存储。在类型中引用指向包含对内存块的引用的存储。 在 C# 中方法的参数是按值传递的返回值是按值返回的。参数的值将传递给该方法。返回参数的值是返回值。 或 修饰符指示参数是通过引用传递的。对存储位置的引用将传递给该方法。添加到方法签名意味着通过引用返回返回值。对存储位置的引用是返回值。 您还可以使用 ref 赋值让一个变量引用另一个变量。典型的赋值将右侧的值复制到赋值左侧的变量。ref 赋值将右侧变量的内存位置复制到左侧的变量。现在指的是原始变量 int anInteger 42; // assignment.
ref int location ref anInteger; // ref assignment.
ref int sameLocation ref location; // ref assignmentConsole.WriteLine(location); // output: 42sameLocation 19; // assignmentConsole.WriteLine(anInteger); // output: 19分配变量时会更改其值。当您 ref 赋值一个变量时您可以更改它所引用的内容。 您可以使用变量、通过引用传递和引用赋值直接处理值的存储。编译器强制执行的范围规则可确保直接使用存储时的安全性。 和修饰符都指示参数应通过引用传递并且不能在方法中重新赋值。区别在于该方法将参数用作变量。该方法可能会捕获参数也可能通过只读引用返回参数。在这些情况下应使用修饰符。否则修饰符将提供更大的灵活性。您无需将修饰符添加到参数的参数中因此您可以使用修饰符安全地更新现有 API 签名。如果未将 or 修饰符添加到参数的参数中编译器将发出警告。 2、引用安全上下文 C# 包含表达式规则以确保在表达式引用的存储不再有效的情况下无法访问表达式。请看以下示例 public ref int CantEscape()
{int index 42;return ref index; // Error: indexs ref safe context is the body of CantEscape
}编译器报告错误因为无法从方法返回对局部变量的引用。调用方无法访问所引用的存储。ref 安全上下文定义表达式可以安全访问或修改的范围。下表列出了变量类型的 ref 安全上下文。 字段不能在 a 或 non-ref 中声明因此这些行不在表中 声明ref 安全上下文非 ref 本地声明 local 的块non-ref 参数current 方法ref参数ref readonlyin调用方法out参数current 方法class田调用方法non-ref 字段structcurrent 方法ref领域ref struct调用方法 如果变量的 ref 安全上下文是调用方法则可以返回该变量。如果其 ref 安全上下文是当前方法或块则不允许返回。以下代码片段显示了两个示例。可以从调用方法的作用域访问成员字段因此类或结构字段的 ref 安全上下文是调用方法。带有 或修饰符的参数的 ref 安全上下文是整个方法。两者都可以从成员方法返回 private int anIndex;public ref int RetrieveIndexRef()
{return ref anIndex;
}public ref int RefMin(ref int left, ref int right)
{if (left right)return ref left;elsereturn ref right;
}编译器确保引用无法转义其引用安全上下文。您可以安全地使用参数、 和局部变量因为编译器会检测您是否意外编写了代码在表达式存储无效时可以访问表达式。 3、安全的上下文和 ref 结构 ref struct类型需要更多的规则来确保它们可以安全使用。类型可以包含字段。这需要引入一个安全的环境。对于大多数类型安全上下文是调用方法。换言之始终可以从方法返回不是 ref structrefref struct的值。 非正式地a 的安全上下文是可以访问其所有字段的范围。换句话说它是其所有字段的 ref 安全上下文的交集。以下方法返回 a to a member 字段因此其安全上下文是该方法ref structrefrefReadOnlySpanchar private string longMessage This is a long message;public ReadOnlySpanchar Safe()
{var span longMessage.AsSpan();return span;
}相反以下代码会发出错误因为 的成员引用了堆栈分配的整数数组。它无法转义方法ref fieldSpanint public Spanint M()
{int length 3;Spanint numbers stackalloc int[length];for (var i 0; i length; i){numbers[i] i;}return numbers; // Error! numbers cant escape this method.
}4、统一内存类型 System.SpanT 和 System.MemoryT 的引入为使用内存提供了统一的模型。System.ReadOnlySpanT 和 System.ReadOnlyMemoryT 提供用于访问内存的只读版本。它们都提供了对存储类似元素数组的内存块的抽象。区别在于 和 是类型而 和 是类型。跨度包含一个 .因此跨度的实例不能离开其安全上下文。a 的安全上下文是其 的 ref 安全上下文。实施并删除此限制。您可以使用这些类型直接访问内存缓冲区。SpanTReadOnlySpanTref structMemoryTReadOnlyMemoryTstructref fieldref structref fieldMemoryTReadOnlyMemoryT 5、通过参考安全提高性能 使用这些功能提高性能涉及以下任务 避免分配将类型从 a 更改为 时会更改其存储方式。局部变量存储在堆栈上。分配容器对象时成员以内联方式存储。此更改意味着分配更少从而减少了垃圾回收器所做的工作。它还可能会降低内存压力从而降低垃圾回收器的运行频率。保留引用语义将类型从 a 更改为 a 会更改将变量传递给方法的语义。修改其参数状态的代码需要修改。现在参数是 该方法正在修改原始对象的副本。您可以通过将该参数作为参数传递来还原原始语义。更改后该方法将再次修改原始内容。避免复制数据复制较大的类型可能会影响某些代码路径的性能。还可以添加修饰符以便通过引用而不是按值将较大的数据结构传递给方法。限制修改当通过引用传递类型时被调用的方法可以修改结构的状态。您可以将修饰符替换为 or 修饰符以指示无法修改参数。当方法捕获参数或通过只读引用返回参数时首选。还可以创建类型或具有成员的类型以便更好地控制可以修改的成员。直接操作内存当将数据结构视为包含一系列元素的内存块时某些算法最有效。和类型提供对内存块的安全访问。 这些技术都不需要代码。如果使用得当您可以从安全代码中获得性能特征而以前只能使用不安全技术才能实现。