C# 如何使用in参数直接调用带有ref参数的方法
我使用的是一个遗留库中的方法:C# 如何使用in参数直接调用带有ref参数的方法,c#,ref,c#-7.2,C#,Ref,C# 7.2,我使用的是一个遗留库中的方法:F(ref T),其中T:struct。它被声明为ref,仅出于性能原因,不修改它接收的数据。此库不能更改 在我的代码中,我有一个新方法G(在T中),其中T:struct调用F 有没有一种方法可以直接用我收到的引用调用F,而无需先将其复制到临时引用?我刚刚读到了“in”。显然,in、ref和out都是一种通过引用调用的形式。然而,主要区别在于“他们的意向声明” 无法修改参数中的。它们只是出于性能原因(如果有的话)参考存在 ref参数可以修改,也可以不修改。这是最接近
F(ref T),其中T:struct
。它被声明为ref
,仅出于性能原因,不修改它接收的数据。此库不能更改
在我的代码中,我有一个新方法G(在T中),其中T:struct
调用F
有没有一种方法可以直接用我收到的引用调用F
,而无需先将其复制到临时引用?我刚刚读到了“in”。显然,in、ref和out都是一种通过引用调用的形式。然而,主要区别在于“他们的意向声明”
无法修改参数中的。它们只是出于性能原因(如果有的话)参考存在
ref
参数可以修改,也可以不修改。这是最接近经典的“引用调用”。实际上,当您通过裸指针实现它时,这是唯一的方法
out
参数有需要修改;如果一个值需要初始化(如构造函数中的只读),这可能是相关的-如果它作为输出变量提交,编译器可以放心它将被设置。其他函数编译器确保了这一点
在某种程度上,
中的是一种“ref,但只读”。无法将收到的内容作为“in”分配给“ref”或“out”,并阻止您意外更改该值。我猜你也不会在那里使用ref(这可能会使它毫无意义)或进行复制。是的,有一种方法(但它使用了不安全的黑魔法)
首先是免责声明
方法F
不修改struct
只是您的“约定”。对于C#编译器,ref
提供的struct
是完全可变的
通过
中的via提供一个由
readonly ref提供的struct
告诉编译器:请确保这个struct
不能被变异
顺便说一下,如果您在中将结构
作为传递,则必须确保该结构
声明为只读结构
。否则,编译器将创建struct
的防御性副本(详细信息请阅读)。这是通常无法将readonly struct
引用传递给通过ref
接受struct
并对其进行变异的方法的第二个原因
如果您仍然想绕过所有这些限制,那么可以使用NuGet包
Unsafe
静态类中有一个方法可以帮助您:
public static ref T AsRef<T>(in T source);
公共静态ref T AsRef(在T源中);
以下是一个例子:
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));
}
void F(参考T),其中T:struct
{
}
void G(在T中),其中T:struct
{
F(ref System.Runtime.CompilerServices.Unsafe.AsRef(在t中));
}
方法是使您的函数也成为ref函数。然后,您只需一路传递引用。In、ref和out的意图声明不同:“in关键字导致参数通过引用传递。它类似于ref或out关键字,只是in参数不能被调用的方法修改。尽管可以修改ref参数,但out参数必须由被调用的方法修改,并且这些修改在调用上下文中是可见的。“在这一点上,我们一直都是正确的工具。但是如果没有这些,你可能也需要使用ref。编译器不允许您在ref参数点上放置in aragument,这正是in存在的原因。很抱歉,这是一个通用的答案,没有太大帮助。我知道关键字的作用。我正在寻找一种绕过正常操作的方法,希望通过一些巧妙的类型转换或类似的方法,而不是使用Emit来实现(这就是我目前正在做的)。我将查看包,谢谢。但是,这是不正确的:“无法将只读结构引用传递给接受struct by ref的方法”。您完全可以这样做,而且不需要防御性副本,因为您不能在ref t
方法中实际修改它,因为它是只读的。@chase,不满意的措辞,精练的。我的意思是:如果您通过
中的获取它,那么它可能是只读的
,因此将它传递给接受引用的方法可能是危险的,因为该方法可能会变异结构
。这确实是一个非常有用的包。使用AsRef
的性能似乎与直接调用相同。还有,不要再发射了,耶!我想我的“不能真正修改它”也可以使用免责声明:不是通过常规方式。不安全、反射等等,所有这些都会从窗口消失,正如这个包奇妙地演示的;)