我真的不明白C#的引用

时间:2013-08-03 05:25:51

标签: c# reference memory-model

英语不是我的母语,我确实是个中国人。如果我不能清楚地表达我的想法,我会很抱歉。

我曾经用c ++编程。我真的不明白C#的参考。很多人告诉我 引用类似于c ++中的指针。如下面的

Person Foo = new Person(); // C#
Person *Foo = new Person(); // C++.

很多时候它运作良好。虽然许多C#编码员也告诉我类的实例是公正的 Foo.Foo有name.whiched被称为Foo.name.Foo有年龄,称为Foo.age。好像是 思想更容易用于编码。但这种思想不符合记忆模型。

请告诉我c#.a对象的引用是什么,或者更可能是指针?Thx。

6 个答案:

答案 0 :(得分:0)

C#具有垃圾收集功能,默认情况下,它不支持指针。但是,您可以使用此处列出的指针http://msdn.microsoft.com/en-us/library/t2yzs44b(v=VS.80).aspx

答案 1 :(得分:0)

您需要熟悉参考类型和值类型之间的差异。

示例如下:

void Main()
{
    Foo A = new Foo{Age = 16}; //A creates a space in memory for the data of Foo and points to that memory location
    Foo B = A; //B just creates a variable and points to the memory location created by A

    A.Bar();
    B.Bar();

    //Result
    //Your Age is 16
    //Your Age is 16

    A.Age = 24;

    A.Bar();
    B.Bar();

    //Result
    //Your Age is 24
    //Your Age is 24  <----- B is pointing to the same location as A and reflects the changes on call.

    FooValueType E = new FooValueType{Age = 23};
    FooValueType F = E;

    E.Bar();
    F.Bar();

    //Result
    //Your Age is 23
    //Your Age is 23

    E.Age = 56;

    E.Bar();
    F.Bar();

    //Result
    //Your Age is 56
    //Your Age is 23
}

public class Foo  //These object are by reference
{
    public int Age { get; set; }
    public void Bar()
    {
       Console.WriteLine("Your Age is {0}", Age);
    }
}

public struct FooValueType //These object are by value
{
    public int Age { get; set; }
    public void Bar()
    {
       Console.WriteLine("Your Age is {0}", Age);
    }
}

答案 2 :(得分:0)

当你说Person Foo = new Person();

时,在C#中
  1. new Person()通过在Person
  2. 中分配内存来创建类heap section的对象
  3. 返回对此对象的引用(即除了reference to memory allocated之外的其他类型)。
  4. Foo捕获此引用时,您可以使用此引用访问对象属性,即methods and variables

    在C ++中,

    它遵循相同的步骤,但在c ++中,您在reference to object类型pointer中捕获Person


    更具体地说,new在内部调用operator new function来分配memory dynamically来创建对象。

    在下面显示的图像中Person pon stack)创建对new Person()返回的对象的引用。

    年龄和名称是Object的成员变量。因此,我们可以使用p.namep.age轻松访问它们。

    enter image description here


    在c#和c ++中添加有关堆栈和堆内存分配的更多内容

    • 引用Foo总是在堆栈上获取内存
    • object,其中new Person()在堆上获取内存,如果C#更具体,则获取内存managed heap

    <强>更新

    当你说new Person()时,它会在内部为类型的对象person分配内存。这个对象由Persons members组成,如图所示。

    然后你可以做两件事

    1. 要么在Person类型的变量中捕获此引用 例如Person p = new Person(); 这里p是对象的内存位置的引用。所以我可以使用p轻松访问对象成员。

    2. 只是不要存储引用直接使用它,例如new Person().age会给我人员年龄。这称为匿名对象。

答案 3 :(得分:0)

关于变量行为,C#中有两种类型:

  • 值类型
  • 参考类型

值类型变量将实际对象作为其值。指定从另一个值类型变量指定的值类型变量复制整个对象。在C ++术语中,这就像使用类类型的变量(不是指向类的指针),例如,当您创建堆栈分配的实例时。但是,C#并没有给出您的选择,但仅将此行为限制为结构类型。

引用类型变量将对实际对象的引用作为其值。对实际对象的引用很可能至少涉及对象的内存地址(但是对您隐藏了详细信息)。从另一个引用类型变量中分配引用类型变量会复制引用,而不是对象,因此现在这两个变量指向同一个对象。在C ++术语中,这就像拥有类的指针变量一样。但是对于类和接口等类型的变量,C#默认为这种行为(据我所知,没有办法跳回到其他行为)。 C#引用和C ++指针之间的主要区别在于C ++指针支持算术,而C#引用则不支持算术。这是C#确保我们称之为内存安全的方式之一。 (C#确实提供了指针,但很少使用它们,很多时候它们在互操作性方案中很有用。在你需要在C#中使用指针之前可能需要很长时间。)

最后,您可以认为C#引用接近于C ++指针(但是,如上所述,存在差异,因为语言行为不同并且为您提供不同程度的控制和保护)。

答案 4 :(得分:0)

在问之前你有google吗?互联网上有许多顶级资源,还有一些不错的电子书。

但是,这里是C#中使用的内存模型(几乎在Java和PHP中):

  1. 每个对象都是从类对象继承的。这意味着,几乎所有东西都是C#中的一个对象。
  2. 你不再需要使用指针了。在C#中几乎不需要它。创建对象时,将返回对堆栈中实例的引用。您还可以对堆栈中的单个对象进行多次引用。引用位于堆中。这是默认行为,您无法更改它,除非您使用本机代码。
  3. 无需删除任何内容。它将由垃圾收集器自动发生。它将删除在结尾处的方法内创建的每个局部变量。垃圾收集器还将删除不再引用的对象。
  4. 内部数据类型始终位于堆栈,字符串也是如此。对于字符串,它们在这里做了一个例外,字符串也被视为简单的数据类型,而不是对象。
  5. 如果您是,则默认情况下将复制每个内部数据类型。 G。给一个方法赋一个int值。这种模式称为“按值调用”。每个对象都将通过新引用传递。这意味着,如果您将对象作为方法paremter,您将只是在方法内部获得对该对象的新引用。此模式称为“按引用调用”。非常重要的是,你可以将它们分开。
  6. 您可以使用“ref”关键字将Call-By-Value更改为Call-By-Reference。您也可以只定义一个out参数。这意味着,无论您为方法赋予什么价值都无关紧要。它只会在方法结束时返回一些内容。这可以通过在C#中使用“out”关键字来完成。
  7. 在逻辑结论中,您无法在C#中溢出堆。因为堆栈会在...之前出现溢出。
  8. 静态和对象调用之间没有任何区别。它总是点。因此,您可以像调用类的公共静态成员一样调用类的公共成员。对于静态成员,您只需要使用类名,或者在变量名之前没有任何关键字的类中使用。您可以通过使用对它的引用来调用对象/类成员。
  9. 您只能从一个类继承。 C#(Java和PHP也是如此)不支持多重继承。
  10. 标准输出命令(&gt;&gt;和&gt;)更改为“控制台”或任何其他流参考,例如: G。文件输出流。
  11. 编辑:

    子类继承基类中的所有内容,也包括私有和受保护的成员/方法。但是您只能访问公共和受保护的成员/方法,除非您不使用反射。 / p>

    希望,这有助于您更多地了解C#...

答案 5 :(得分:-2)

引用是指向对象的指针。

您可以在不安全的代码中使用C#中的“真实”指针:here is an example