如何在参数

时间:2018-12-05 15:09:17

标签: c# ref c#-7.2

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

在我的代码中,我有一个调用G (in T t) where T: struct的新方法F

有没有一种方法可以直接使用我收到的参考来调用F而不先复制到临时参考?

2 个答案:

答案 0 :(得分:3)

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

首先是免责声明。

方法F不会修改struct的事实仅是您的“惯例”。对于C#编译器,struct提供的ref是完全可变的。

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

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

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

Unsafe静态类中有一个可以帮助您的方法:

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

答案 1 :(得分:-2)

我刚刚读了“ in”。显然,ref和out都是通过引用进行调用的一种形式。但是主要的区别是“他们的意图陈述”。

in参数无法修改。出于性能原因,它们仅在此处提供参考。

ref参数可以修改也可以不修改。它最接近经典的“按引用调用”。确实,这是通过裸指针实现它的唯一方法

out自变量需要修改;如果值需要初始化(例如,构造函数中的只读),则这可能是相关的-如果将其作为out变量进行输入,则编译器可以放心设置。其他函数编译器确保了这一点。

在某种程度上,in是一种“引用,但只读”。无法将接收到的内容作为“输入”分配给“参考”或“输出”,也无法阻止您偶然更改值。我猜您也不会在那里使用ref(因为这可能毫无意义)或进行复制。