当我在 C# 中将 `ref` 值分配给 `out` 参数时会发生什么?

左出口

我正在编写一个检索二进制数据并支持将其一般转换为原始类型的类。它应该尽可能高效。这是它现在的样子:

public abstract class MemorySource {
    public abstract Span<byte> ReadBytes(ulong address, int count);

    public unsafe bool TryRead<T>(ulong address, out T result) where T : unmanaged {
        Span<byte> buffer = ReadBytes(address, sizeof(T));
        result = default;
        // If the above line is commented, `result = ref <...>` won't compile, showing CS0177.
        if (!buffer.IsEmpty) {
            result = ref Unsafe.As<byte, T>(ref buffer.GetPinnableReference());
            return true;
        } else
            return false;
    }
}

由于我正在使用大量内存,因此我的代码将执行大量小型读取操作。我想尽量减少内存被复制的次数。

ReadBytes实现将a)在堆上已经存在的数组的一部分上创建一个跨度,或者b) stackalloc一个缓冲区并用来自远程源的数据填充它(取决于我将使用的数据)。关键是,它不会自己在堆上分配任何东西。

我希望我的TryRead<T>方法返回对跨度内存的类型化引用,而不是将该内存复制到新值中,我想知道这是否可能。我注意到我不能在没有初始化的情况下refout参数赋值,但我可以,如果我们假设我正在分配一个引用,这就没有意义了。

我想我要问的是,这段代码到底发生了什么?我是返回对现有值的引用,还是将该值复制到新的堆栈分配值中?堆栈分配和堆分配的跨度的行为有何不同?T如果使用堆分配的跨度,GC 是否知道在移动数据时更新类型的引用

查理脸

无论如何,原始类型都是值类型,因此在读取它们时您不必担心在堆上分配。

您不能使用stackalloc此代码,因为您不能(或不应尝试)返回指向它的指针,因为它将在函数结束时被销毁。

到目前为止,您拥有的代码很危险,因为您正在返回一个实际上并未固定的可固定引用。

您遇到ref参数问题的原因是因为else您根本没有分配它。您应该将result = default;线移到else分支中。


无论哪种方式,您最好使用MemoryMarshal所有这些,请注意,这不需要不安全的代码

public bool TryRead<T>(ulong address, out T result) where T : unmanaged
{
    ReadOnlySpan<byte> buffer = ReadBytes(address, sizeof(T));
    if (!buffer.IsEmpty)
    {
        result = MemoryMarshal.Read<T>(buffer);
        return true;
    }
    result = default;
    return false;
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在Python中将一个变量的值分配给另一个变量时会发生什么?

当我使用切片语法“ mylist [:] = [mylist,mylist,...]”将带有自我引用的列表分配给列表副本时会发生什么情况?

当我从本地Java方法抛出C ++异常时会发生什么?

当我分配大于字节的值时会发生什么?

当我在C ++中对未初始化的指针调用“删除”时会发生什么?

当我使用'|'时会发生什么 或'<',c ++

在C ++ / CLI中将新值分配给不可变值结构

当我们在C ++中更改字符串的值时会发生什么

为什么在C ++中将双重参考值分配给float变量时不变

为什么我不能在C ++中将一个迭代器分配给另一个?

当我在C ++中存储指向按值传递参数的指针时会发生什么?

当我在C语言中省略函数的参数时会发生什么?

为什么我分配给变量的值消失了?

为什么我不能在Kotlin中将空值类型分配给Any?

当我们通过该函数传递值结果时会发生什么?

为什么我可以在C ++中将常量shared_ptr分配给非常量shared_ptr?

当我在函数中重新分配可变默认参数时会发生什么?

当我们在C中将数字转换为较小的数字时,会发生什么情况?

为什么我不能在C ++中将整数值分配给整数指针?

当我们将参数传递给System.out.println()时会发生什么?

当我在C ++中对类使用vector时会发生什么

如果我将一个右值分配给一个类的指针成员会发生什么?

当我们将 2 个值分配给同一个变量时会发生什么?

在 C 中将 var 分配给 var

当我们改变循环中的值时会发生什么?

当我们在 C++ 中使用“while”时会发生什么转换?

当我们为变量分配引用时会发生什么?

通用 C - 当我调用“struct *s”时会发生什么?

当我的 Python 范围对象停止值从未被命中时会发生什么?