Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取对装箱值类型的引用_C#_.net - Fatal编程技术网

C# 获取对装箱值类型的引用

C# 获取对装箱值类型的引用,c#,.net,C#,.net,是否有一种简单的方法(可能是使用System.Memory软件包)来获取存储在值类型的盒装实例中的内部数据的(只读)引用(如ref T,in T,Span或Memory) 我提出了这个解决方案,但它需要锁定对象并使用不安全的 object o = 1; var handle = GCHandle.Alloc(o, GCHandleType.Pinned); Span<int> span; try { var addr = handle.AddrOfPinnedObject()

是否有一种简单的方法(可能是使用System.Memory软件包)来获取存储在值类型的盒装实例中的内部数据的(只读)引用(如
ref T
in T
Span
Memory

我提出了这个解决方案,但它需要锁定对象并使用
不安全的

object o = 1;
var handle = GCHandle.Alloc(o, GCHandleType.Pinned);
Span<int> span;
try
{
    var addr = handle.AddrOfPinnedObject();
    unsafe
    {
        span = new Span<int>(addr.ToPointer(), 1);
    }
} finally
{
    handle.Free();
}
ref int r = ref span[0];
对象o=1;
var handle=GCHandle.Alloc(o,GCHandleType.pinted);
跨度;
尝试
{
var addr=handle.addrofpindedObject();
不安全的
{
span=新span(addr.ToPointer(),1);
}
}最后
{
handle.Free();
}
ref int r=参考范围[0];
是.NET Core 3.0中的新功能,它是
unbox
上的一个简单包装器,将对象作为
ref
返回。它在
Unsafe
类中是正确的,因为运行时不允许通过用另一个值覆盖来改变装箱的值,也就是说,类型本身必须只允许对内容进行更改(与引用类型一样)。这被称为可控的可变异指针,它不能在.NET类型系统中表示(以C++为基础,想象一个指向非const对象的指针,它在访问时从其类型中删除<代码>运算符=< /代码>)。
对于支持emit的平台,当然总是可以使用
unbox
unbox\u any
指令创建动态方法。违反可变性约束将使代码无法验证(例如
不安全。Unbox
是)。

引用值类型是一种矛盾修饰法。您只能对引用类型使用引用…@ZoharPeled
ref int
是对值类型的引用。装箱对象是引用,您可以通过取消装箱来访问interiour<代码>对象o=1;int n=(int)o
。但您的源代码正朝着完全不同的方向发展,更像是托管/非托管内存。我想你还想问另一个问题。对于任何操作,只需手动和显式地执行“装箱”,而不是使用.NET提供的自动操作。@IllidanS4wantsMonicaback是的,这是正确的。我的意思是,持有值类型的变量实际上持有值本身,这与引用类型类似,在引用类型中,变量持有对值的引用。如果你有
int x=5
,那么
x
会保持
5
,而不是对
5
@ZoharPeled的引用,这是事实上正确的,但与问题无关。有任何关于运行时为什么不允许变异的引用吗?我还想知道为什么这个规则只适用于只读字段。否则,运行时永远不会强制执行readonly。好的,在III.1.8.1.2.2和中有一些内容。ECMA中的规则非常奇怪。只要存在任何mutator方法,就可以使类型成为非只读类型。即使使用这种方法,也没有关系。这显然不是经过深思熟虑的…@usr我会从另一个方向解释:缺少mutator方法/字段会使类型严格为只读,这是受控可变指针性质的直接结果:您只能通过类型本身允许的方式对其进行变异,因此如果它们不公开任何此类选项,它们实际上是只读的。这更多的是出于实际目的的简化,而不是限制。@usr此规则的目的是对齐装箱值类型和引用类型。引用类型只能通过调用其方法或修改公共字段从一种状态转到另一种状态。不能将一种引用类型的内容复制到另一种引用类型;例如,想象一下这会对字符串产生什么影响。值类型本身没有标识,但装箱为它们提供了标识,并且必须像类一样维护它们的完整性。我记得在泛型之前,一些平台使用对象True和False作为两个布尔值的装箱代表。修改它们会导致崩溃everything@usr不过,也许在我的回答中,我可能过于简化了限制;我将更新它并添加原因。