我正在使用旧版库中的一种方法:F (ref T t) where T: struct
。仅出于性能原因将其声明为ref
,并且不会修改接收到的数据。该库无法更改。
在我的代码中,我有一个调用G (in T t) where T: struct
的新方法F
。
有没有一种方法可以直接使用我收到的参考来调用F
而不先复制到临时参考?
答案 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(因为这可能毫无意义)或进行复制。