如何通过引用传递c#结构体
本文关键字:结构体 何通过 引用 | 更新日期: 2023-09-27 18:14:03
在我的c#应用程序中,我在回调/委托中收到一个指向c++结构体的指针。我不确定class
是否可以做到这一点,但只是将c++指针转换为适当的c#结构体就可以了,所以我使用c#结构体来存储数据。
现在我想传递一个引用到结构体,以便进一步处理。
- 我不能使用
class
,因为它可能不会"映射"。 - 我不想复制结构体以获得更好的延迟。
我该怎么做呢?
这个例子说明了struct是按值传递的,而不是按引用传递的:
using System;
namespace TestStruct
{
struct s
{
public int a;
}
class Program
{
static void Main(string[] args)
{
s s1 = new s
{
a = 1
};
Foo(s1);
Console.WriteLine("outer a = " + s1.a);
}
private static void Foo(s s1)
{
s1.a++;
Console.WriteLine("inner a = " + s1.a);
}
}
}
输出是:
inner a = 2
outer a = 1
听起来你只是想使用ref
通过引用传递结构体:
private static void Foo(ref s s1)
{
s1.a++;
Console.WriteLine("inner a = " + s1.a);
}
在呼叫现场:
Foo(ref s1);
请参阅我关于c#中参数传递的文章。
注意,除了互操作,我通常强烈建议而不是使用这样的可变结构体。我能理解这样做的好处。
您可以使用c# 7.2 in
关键字如下:
static float Sample(in Vector3 v)
{
// v.X = 2; // <-- this generate follow compiler error
// error CS8332: Cannot assign to a member of variable 'v'
// or use it as the right hand side of a ref assignment
// because it is a readonly variable
return v.X;
}
这确保结构体参数v是:
- 只读的
- 通过ref
Vector3 v = Vector3.One;
float Sample(Vector3 v)
{
return v.X;
}
System.Console.WriteLine(Sample(v));
float ReadonlySample(in Vector3 v)
{
return v.X;
}
System.Console.WriteLine(ReadonlySample(v));
produce follow IL:
// Vector3 v2 = Vector3.One;
IL_0001: call valuetype [System.Numerics.Vectors]System.Numerics.Vector3 [System.Numerics.Vectors]System.Numerics.Vector3::get_One()
IL_0006: stloc.0
// Console.WriteLine(Sample(v2));
IL_0007: nop
IL_0008: ldloc.0
IL_0009: call float32 test_console.Sample::'<Main>g__Sample|0_0'(valuetype [System.Numerics.Vectors]System.Numerics.Vector3)
IL_000e: call void [System.Console]System.Console::WriteLine(float32)
// (no C# code)
IL_0013: nop
// Console.WriteLine(ReadonlySample(in v2));
IL_0014: nop
IL_0015: ldloca.s 0
IL_0017: call float32 test_console.Sample::'<Main>g__ReadonlySample|0_1'(valuetype [System.Numerics.Vectors]System.Numerics.Vector3&)
IL_001c: call void [System.Console]System.Console::WriteLine(float32)
你可以看到使用in
我们用ldloca代替ldloc。
简而言之,该结构体像ref
一样传递,但由于in
,编译器保护它不能写。