如何使用 in 参数直接调用带有 ref 参数的方法

How to directly call a method with ref parameter using in parameter

我正在使用旧库中的方法:F (ref T t) where T: struct。仅出于性能原因将其声明为 ref,并且不会修改它接收到的数据。此库无法更改。

在我的代码中,我有一个调用 F.

的新方法 G (in T t) where T: struct

有没有一种方法可以直接使用我收到的参考调用 F 而无需先将其复制到临时文件?

我刚刚阅读了 "in"。显然,in、ref 和 out 都是引用调用的一种形式。然而,主要区别是 "their statement of intent".

in 参数无法修改。如果有的话,它们只是出于性能原因的参考。

ref 参数可以修改也可以不修改。它最接近经典"call by reference"。事实上,这是您通过裸指针实现它时获得的唯一方法

out 个参数 个要修改;如果一个值需要初始化(比如构造函数中的只读),这可能是相关的 - 如果它作为输出变量提交,编译器可以放心它 被设置。其他函数编译器确保了这一点。

在某种程度上 in 是一种 "ref, but readonly"。无法将收到的 "in" 分配给 "ref" 或 "out" 以及阻止您 意外地 更改值。我想你也不会在那里使用 ref(这可能毫无意义)或进行复制。

是的,有办法(但它使用了不安全的黑魔法)。

首先是免责声明。

方法 F 不修改 struct 的事实只是你的 "convention"。对于 C# 编译器,ref 提供的 struct 是完全可变的。

readonly ref 通过 in 提供的 struct 告诉编译器:请确保这个 struct 不能被改变。

顺便说一句,如果您将 struct 作为 in 传递,您 必须 确保此 struct 被声明为readonly struct。否则,编译器将创建 struct 的防御性副本(有关详细信息,请阅读 here。)这是您 通常 无法传递 [=23] 的第二个原因=] 引用通过 ref 接受 struct 并对其进行变异的方法。

如果您仍想解决所有这些限制,可以使用 System.Runtime.CompilerServices.Unsafe NuGet 包。

Unsafe静态class中有一个方法可以帮助你:

public static ref T AsRef<T>(in T source);

这是一个例子:

void F<T>(ref T t) where T : struct
{
}

void G<T>(in T t) where T : struct
{
    F(ref System.Runtime.CompilerServices.Unsafe.AsRef(in t));
}