.net 为什么指针是引用类型?

.net 为什么指针是引用类型?,.net,reflection,.net,Reflection,本周我一直在研究一些基于反射的代码,在单元测试期间发现了一个意外情况:指针是引用类型。C#codetypeof(int).MakePointerType().IsClass返回true 我签入了我刚到达的带注释的CLI标准,果然,指针被明确定义为引用类型 这对我来说是个意外,来自C++背景。我刚才假设指针是值类型 指针类型是引用类型而不是值类型有什么特殊原因吗 更新(澄清) 当谈到指针和引用时,关于“指针”和“指针对象”,事情往往会变得混乱。所以这里有一些澄清 类型可以是引用类型或值类型,但变量

本周我一直在研究一些基于反射的代码,在单元测试期间发现了一个意外情况:指针是引用类型。C#code
typeof(int).MakePointerType().IsClass
返回
true

我签入了我刚到达的带注释的CLI标准,果然,指针被明确定义为引用类型

这对我来说是个意外,来自C++背景。我刚才假设指针是值类型

指针类型是引用类型而不是值类型有什么特殊原因吗

更新(澄清)

当谈到指针和引用时,关于“指针”和“指针对象”,事情往往会变得混乱。所以这里有一些澄清

类型可以是引用类型或值类型,但变量略有不同。(很抱歉,我没有机会阅读我的CLI标准,因此术语和概念可能是错误的-请纠正我!)

给定此代码(引用类型的局部变量概念):

变量
x
y
实际上不是引用类型,但它们是对作为引用类型的对象的引用(
MyClass
是引用类型)。换句话说,
x
y
不是引用类型的实例;它们仅引用引用类型的实例

给定此代码(值类型的局部变量概念):

变量
x
y
是实例值类型(或者至少表现为实例)

那么我们来看看这个代码:

var i = 13;
var x = &i;
var y = x;
如果指针类型是引用类型,那么这就是我如何解释语句
x=&I

  • 创建类型为
    int*
    的实例,指向
    i
  • 因为指针是引用类型,所以这个实例是在堆上创建的(假设所有引用类型都放在堆上,这是一个实现细节)
  • x
    是对该指针实例的引用
  • 指针实例最终将被垃圾收集,就像其他引用类型一样
  • 执行
    y=x
    时,复制引用。
    y
    x
    都引用指针对象的同一实例
  • 也许我的解释完全错了


    来自C++背景的指针对值类型的理解更为合理,因此语句<代码> x=和i >代码>只将代码< >代码>的地址分配给值类型<代码> x>代码>的实例,以及<代码> y= x < /Cord> >将地址值复制到<代码> y>代码>。不会在堆上创建“指针对象”。

    它们是引用类型,因为它们不包含目标对象的实际值:就像引用一样,它们只“指向”目标对象。

    请考虑:

    MyClass x = new MyClass();
    
    这里,MyClass是一种引用类型,如果您通过反射查看,x将被称为引用类型。但是,在引擎盖下面,x实际上是一个指针。

    typeof(int).MakePointerType().IsPointer


    似乎有区别。

    这只是一个理论,但它是否与以下事实有关:由于垃圾收集系统和堆压缩,当对象在内存中移动时,指针必须调整。通过创建托管指针引用类型,它们可以以与任何其他引用相同的方式重新指向,而不必将其作为特例

    更新

    Wesner Moise的一篇优秀文章:“


    在本文中,他描述了如何在堆压缩期间调整托管指针

    我还没有看到一个完整的答案,所以我现在结束这个问题


    我不得不得出结论:指针(例如,
    int*
    );对于
    IsClass
    ,他们的
    Type
    s返回
    true
    ,这是规范中的一个错误。我怀疑没有人注意到这一点,因为获取指针类型是一个非常罕见的操作。

    从type.IsClass上的CLR文档中-'获取一个值,指示该类型是否为类;也就是说,不是“值类型或接口”。从技术上讲,指针类型不是继承自
    System.Object
    ,因此它不是对象、值类型或接口,而是文档中的类。指针类型(
    int*
    )与普通对象是完全不同的实体reference@thecoop引用在概念上与指针没有什么不同。两者都包含一些其他数据的内存地址,可以是
    int
    原语或
    MyClass
    对象。主要区别在于引用通常是不可变的(引用本身,而不是它们引用的内容);可以确定引用类型是否为指针。我的问题是为什么指针是引用类型而不是值类型(请参阅更新的问题)。CLR区分托管和非托管指针类型,请参阅CLR规范中分区I的12.1.1.1。托管指针可能会被GC更改(移动)。我认为这可能是它们成为类类型的原因。另请参见第14.4节分区II-特殊类型/指针类型。我更新了这个问题,以便更清楚地说明引用类型与引用变量。我相信指针只能指向固定对象-。不过我会读那篇文章;看起来很有趣!你看到那张照片了吗?根据它的说法:在不安全的上下文中,类型可以是指针类型、值类型或引用类型。所以你不能把它们既当作值类型也当作引用类型吗?这是有道理的。但它并没有回答我的问题:为什么指针引用类型(即,它们从
    IsClass
    返回
    true
    )?请参见图中的另一个自相矛盾的语句。指针列在引用类型下。
    var i = 13;
    var x = &i;
    var y = x;
    
    MyClass x = new MyClass();