2

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

我以前用c++编程。我真的不明白C#的引用。很多人告诉我引用类似于c++中的指针。如下所示

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

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

请告诉我 c# 中的引用是什么。一个对象,或者更可能是一个指针?谢谢。

4

6 回答 6

0

你在问之前用谷歌搜索过吗?互联网上有很多顶级资源,也有一些不错的电子书。

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

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

编辑:

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

希望这可以帮助您更多地了解 C#...

于 2014-04-27T17:47:50.777 回答
0

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

于 2013-08-03T05:35:52.010 回答
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);
    }
}
于 2013-08-03T05:37:10.453 回答
0

在 C# 中,当你说Person Foo = new Person();

  1. new Person()Person通过分配内存来创建类的对象heap section
  2. 返回对reference to memory allocatedPerson 类型的这个对象的引用(即除了 之外什么都没有)。

虽然Foo捕获此引用并使用此引用,您可以访问对象属性,即它的methods and variables.

在 C++ 中,

它遵循相同的步骤,但在 c++ 中,您可以捕获 a类型reference to object的 a 。pointerPerson


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

在下面显示的图像中,Person p( on stack) 创建了对由 . 返回的对象的引用new Person()

age 和 name 是 Object 的成员变量。因此我们可以使用p.name和轻松访问它们p.age

在此处输入图像描述


更多关于 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会给我人员年龄。这称为匿名对象。

于 2013-08-03T05:38:23.880 回答
0

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

  • 值类型
  • 引用类型

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

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

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

于 2013-08-03T08:45:18.327 回答
-2

引用是指向对象的指针。

您可以在不安全的代码中使用 C# 中的“真实”指针:这是一个示例

于 2013-08-03T05:34:43.573 回答