c#类型引用(vs C)

时间:2019-02-10 17:14:03

标签: c# pointers

如果类是引用,则c#引用如何工作
class1 a = new class1();
 因此地址“ a”包含 指示mem [0]的对象的地址,所以它是一个指针

为什么

method(class1 a);

将对象的值复制到本地方法实例而不是mem [0]的地址吗?
是否隐式取消引用(*)a? 如果是这样,那么ref修饰符会取消它吗?

让我们说一个类定义一种地址类型,以指向指向对象各个点的地址。我仍然无法结束...

3 个答案:

答案 0 :(得分:2)

  

为什么method(class1 a)将对象的值复制到本地方法

这是一个错误的假设。方法参数a包含对该对象的引用。如果您使用method(ref class1 a),则会获得对传递给方法的变量的引用,该变量又包含对对象的引用

给予

class1 a = new class1();
method(ref a);

在方法中,您可以为参数分配一个新对象,这将更改a

void method(ref class1 b)
{
    b = new class1(); // This changes a!
}

如果缺少ref关键字,则该方法将获取引用的副本(而不是对象的副本!)

void method(class1 b)
{
    b = new class1(); // This does NOT change a.

    // But
    b.IntProperty = 5; // This changes a property of a.
}

在C#中,您不必使用*。 C#知道哪些类型是引用,哪些类型是值类型,并对其进行相应处理。

对于常规参数:

  • 对于值类型:传递值的副本。
  • 对于引用类型:传递值的副本(是!)。该值恰好是参考(或null)。即,没有对象被复制。

对于ref参数:

  • 对于值类型:传递对包含值的变量的引用。
  • 对于引用类型:传递对包含引用(或null)的变量的引用。

换句话说,对于ref参数,参数名称只是方法调用中使用的变量的别名。


如果发现此问题令人困惑,则有助于在编辑器中配置颜色,以帮助区分引用类型和值类型。在Visual Studio中:转到菜单Tools> Options...,然后依次转到Environment> Fonts and Colors并更改User Types - Structures的颜色(即值类型)以显示为不同的颜色作为类(我正在使用Olive)。您还可以更改其他User Types(我将红色用于代表,将深橙色用于枚举,将紫色用于接口,将一种霓虹绿色用于类型参数。

答案 1 :(得分:1)

您将必须了解如何调用方法以及如何在内存中分配对象。

所有类类型都是C#中的引用类型-从 System.Object 继承。

  

支持.NET Framework类层次结构中的所有类以及   为派生类提供底层服务。这是终极的   .NET Framework中所有类的基类;这是   类型层次结构。

参考:MSDN Documentation of System.Object

意味着,它们将在堆中分配。他们的参考文献将被复制到某个地方。该变量保存引用被复制的地方。

在方法调用的情况下,将对象的地址复制到调用堆栈。它指向相同的地址。

因此,即使您更改了该类的任何属性(值类型),即使您不使用ref关键字,您仍然可以在调用者方法中访问更改后的值。

void Method(Class A)

从技术上讲,ref关键字提供相同的地址位置-而不是将此地址复制到新位置。

希望这能回答您的查询。

答案 2 :(得分:1)

是的,从这个意义上讲,您可能想将C#类变量视为(安全的)C指针。它们只是不允许您操纵它们指向内存的位置(甚至允许运行时重新分配和移动它们)。

如果您的class1是类类型(而不是struct类型或ValueType),那么您不正确地认为method将复制整个a对象。相反,它的作用就像您在C中传递了一个指针。但是就像在C中一样,*p1==*p2p1==p2&p1!=&p2

由于类变量仅存储引用(类似于C指针),因此如果method突变了a所引用的对象,则这些突变将在method返回后保留。然后,通过ref传递类变量类似于将指针传递给C中的指针。但是在C#中几乎不可能是一个好的设计思想。

这是 class 变量(包括字符串)的行为方式。但是,还有值类型(除字符串和对象以及结构以外的所有基本类型)在赋值时被复制,除非通过ref或out传递。

进一步阅读: