简体   繁体   English

我真的不明白C#的参考

[英]I really don't understand the reference of C#

English is not my mother tongue, exactly I am a Chinese. 英语不是我的母语,而我恰恰是中国人。 I'll be sorry if I cannot express my idea clearly. 如果无法明确表达我的想法,我将感到抱歉。

I used to programme with c++. 我曾经用c ++编程。 I really dont's understand the reference of C#.Many people tell me the reference is similar to the pointer in c++.Such as below 我真的不了解C#的引用,很多人告诉我该引用类似于c ++中的指针。

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

Many times it works well.While many C# coders also tell me that the instance of class is just the Foo.Foo has name.whiched is called Foo.name.Foo has age,which is called Foo.age. 很多时候,C#编码器还告诉我,类的实例就是Foo。Foo的名称为Foo.name。Foo的年龄为Foo.age。 It seems the thought is more easy to be used to code.But this thought does not conform to Memory model . 似乎这种想法更易于编码。但是这种想法不符合Memory模型。

Please tell me What the reference is in c#.a object,or more likely a pointer?Thx. 请告诉我c#.a对象中的引用是什么,或更可能是指针?

C# has garbage collection and by default, it does not support pointers. C#具有垃圾回收,默认情况下,它不支持指针。 You can however, use pointers as outlined here http://msdn.microsoft.com/en-us/library/t2yzs44b(v=VS.80).aspx 但是,您可以使用此处概述的指针http://msdn.microsoft.com/zh-cn/library/t2yzs44b(v=VS.80).aspx

You will want to get familiar with the different between Reference Type and Value Type. 您将要熟悉引用类型和值类型之间的区别。

Example is below: 示例如下:

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);
    }
}

In C# when you say Person Foo = new Person(); 在C#中,当您说Person Foo = new Person();

  1. new Person() creates an object of the class Person by allocating memory in heap section new Person()通过在heap section分配内存来创建Person类的对象
  2. returns a reference to this object (ie nothing but reference to memory allocated ) of type Person. 返回对该类型Person的对象的引用(即reference to memory allocated )。

While Foo catches this reference and with this reference you can access the objects properties ie its methods and variables . Foo捕获此引用时,通过此引用,您可以访问对象的属性,即其methods and variables

In C++, 在C ++中,

It follows the same steps but in c++ you catch a reference to object in a pointer of type Person . 它遵循相同的步骤,但是在c ++中,您在Person类型的pointer中捕获了reference to objectreference to object


More specifically new internally calls operator new function to allocate a memory dynamically to create objects. 更具体地说, new内部调用operator new functionmemory dynamically分配memory dynamically以创建对象。

In the image shown below Person p ( on stack ) creates an reference to an object returned by new Person() . 在下面显示的图像中, Person pon stack )创建对new Person()返回的对象的引用。

age and name are the member variables of the Object.So we can easily access them using p.name and p.age . age和name是Object的成员变量。因此,我们可以使用p.namep.age轻松访问它们。

在此处输入图片说明


More to add about stack and heap memory allocation in both c# and c++ 有关在C#和C ++中堆栈和堆内存分配的更多信息

  • The reference Foo always gets a memory on stack 引用Foo总是在堆栈上获取内存
  • Where object ie here new Person() gets memory on heap and in case of C# more specifically it gets memory on managed heap object即这里new Person()在堆上获取内存,更具体地说,在C#情况下,它在managed heap获取内存

Updates 更新

When you say new Person() it internally allocates memory for the Object Of the type - person .This object is composed of Persons members like shown in image. 当您说new Person()它会在内部为类型为person的对象分配内存。该对象由Persons members组成,如图所示。

You then can do two thing 然后,您可以做两件事

  1. Either you catch this reference in variable of type Person eg Person p = new Person(); 您可以在Person类型的变量中捕获此引用,例如Person p = new Person(); Here p is a reference to memory location of object.So I can easily access Objects member using p . 这里p是对对象存储位置的引用,因此我可以使用p轻松访问Objects成员。

  2. Just don't store the reference directly use it eg new Person().age will give me Persons age.This is called an anonymous Object. 只是不要直接使用引用来存储引用,例如new Person().age会给我Persons年龄。这称为匿名对象。

With respect to the variable behaviors, there are two kinds of types in C#: 关于变量行为,C#中有两种类型:

  • Value types . 值类型
  • Reference types . 参考类型

Value type variables carry the actual object as their value. 值类型变量将实际对象作为其值。 Assigning a value type variable assigned from another value type variable copies the whole object . 分配从另一个值类型变量分配的值类型变量将复制整个对象 In C++ terms, this is like using a variable of the class type (not a pointer to the class) like for example when you're making a stack allocated instance. 用C ++术语来说,这就像使用类类型的变量(而不是指向该类的指针)一样,例如在创建堆栈分配的实例时。 C# however doesn't give you that choice, but restricts this behavior only to such types as structs. 但是,C#并没有给您这种选择,而是仅将此行为限制为诸如struct之类的类型。

Reference type variables carry a reference to the actual object as their value. 引用类型变量将对实际对象的引用作为其值。 A reference to the actual object will most probably at least in involve the memory address of the object (but the details are hidden from you). 对实际对象的引用很可能至少会涉及对象的内存地址(但详细信息对您而言是隐藏的)。 Assigning a reference type variable from another reference type variable copies the reference, not the object , so now the two variables point to the same object. 从另一个引用类型变量分配引用类型变量将复制引用,而不是对象 ,因此现在这两个变量指向同一个对象。 In C++ terms, this is like having a pointer variable of the class. 用C ++术语来说,这就像具有该类的指针变量一样。 C# however defaults to this behavior for variables of such types as classes and interfaces (and there's no way to jump back to the other behavior, as far as I know). 但是,对于类和接口等类型的变量,C#默认使用此行为(据我所知,无法跳回其他行为)。 The major difference between C# references and C++ pointers is that C++ pointers support arithmetic, while C# references don't. C#引用和C ++指针之间的主要区别在于C ++指针支持算术,而C#引用不支持算术。 This is one of the ways C# ensures what we call memory safety . 这是C#确保我们所谓的内存安全性的方法之一 (C# does offer pointers, but they are used rarely and a lot of the time they are useful in interoperability scenarios. It'll likely be a long time before you ever need to use a pointer in C#.) (C#确实提供了指针,但是在互操作性场景中很少使用它们,并且在很多时候它们很有用。在C#中需要使用指针可能要花很长时间。)

In the end, you can think that the C# reference is close to the C++ pointer (but, as outlined above, there are differences because the languages behave differently and give you different degrees of control and protection). 最后,您可以认为C#引用接近C ++指针(但是,如上所述,它们之间存在差异,因为语言的行为不同,并且为您提供不同程度的控制和保护)。

Have you googled that before asking? 在询问之前,您已经用谷歌搜索过吗? There are many top resources on the internet and also some nice e-books. 互联网上有许多顶级资源,也有一些不错的电子书。

However, here´s the memory model used in C# (in Java and PHP nearly as well): 但是,这是C#中使用的内存模型(在Java和PHP中也是如此):

  1. Every object is inherited from the class object. 每个对象都从类对象继承。 That means, that nearly everything is an object in C#. 这意味着,几乎所有内容都是C#中的对象。
  2. You don´t need to use pointer anymore. 您不再需要使用指针。 There´s nearly no need in C# for it. C#几乎不需要它。 When you create an object, you will get back an reference to the instance in the stack. 创建对象时,您将获得对堆栈中实例的引用。 You could also have many references to one single object in stack. 您可能还对堆栈中的单个对象有很多引用。 The references are located in the heap. 引用位于堆中。 This is the default behaviour and you aren´t able to change it, unless you do native code. 这是默认行为,除非您执行本机代码,否则您将无法更改它。
  3. There´s no need of deleting something. 无需删除任何内容。 It will be automatically happened by the Garbage Collector. 这将由垃圾收集器自动发生。 It will be delete every local variable which is created inside a method at the end of it. 它将删除在其末尾在方法内部创建的每个局部变量。 The Garbage Collector will also delete objects, which got no reference anymore. 垃圾收集器还将删除不再有引用的对象。
  4. Internal datatypes are always located at the stack, strings also. 内部数据类型始终位于堆栈中,字符串也位于。 For strings, they made an exception here, strings are also treated as simple datatypes, not as an object. 对于字符串,这里是一个例外,字符串也被视为简单数据类型,而不是对象。
  5. Every internal datatype will be copied per default, if you eg have give an int value to a method. 如果您为方法提供了一个int值,则默认情况下将复制每个内部数据类型。 This pattern is called "Call-By-Value". 此模式称为“按值打电话”。 Every object will be passed by a new reference. 每个对象都将通过新的引用传递。 That means, if you give an object as a method paremter, you will just get inside the method a new reference to the object. 这意味着,如果将一个对象作为方法的参数,那么您将在该方法内部获得对该对象的新引用。 This pattern is called "Call-By-Reference". 此模式称为“按引用呼叫”。 It´s very important, that you might divide in them. 非常重要,您可以将它们分开。
  6. You can change Call-By-Value to Call-By-Reference using the "ref" keyword. 您可以使用“ ref”关键字将“按值发送”更改为“按引用发送”。 You could also define only an out parameter. 您也可以只定义一个out参数。 That means, that doesn´t matter what value you give to a method. 这意味着,给一个方法带来什么价值都没有关系。 It will only return something at the end of the method. 它只会在方法结束时返回某些内容。 This can be done by using the "out" keyword in C#. 这可以通过在C#中使用“ out”关键字来完成。
  7. In logical conclusion to this, you are not able to overflow the heap in C#. 从逻辑上得出结论,您无法在C#中溢出堆。 Because the stack would get an overflow before... 因为堆栈在...之前会溢出...
  8. There´s no difference anymore between static and object-calls. 静态调用和对象调用之间不再存在任何区别。 It´s always the dot. 总是点。 So, you could call public members of a class in the same way you would also call public static members of the class. 因此,您可以像调用类的公共静态成员一样调用类的公共成员。 For static members, you just need to use the class name, or inside the class without any keyword before the variable name. 对于静态成员,您只需要使用类名,或在类内部使用变量名前没有任何关键字的类。 You call object/class member by using a reference to it. 您通过使用对对象/类成员的引用来对其进行调用。
  9. You could only inherit from one class. 您只能从一个类继承。 Multiple inheritance is not supported it C# (Java and PHP as well). C#不支持多重继承(以及Java和PHP)。
  10. Stdout commands (>> and >) changes to "Console" or to any other stream reference, eg file output streams. 标准输出命令(>>和>)更改为“控制台”或任何其他流引用,例如文件输出流。

Edit: 编辑:

A child class inherits everything from the base class, also private and protected members/methods. 子类继承基类的所有内容,还继承私有和受保护的成员/方法。 But you can only access public and protected members/methods, unless you dont´ make use of reflections. 但是除非您不使用反射,否则您只能访问公共成员和受保护的成员/方法。

Hope, this helps you in order to unterstand C# a bit more... 希望这可以帮助您进一步理解C#。

The reference is a pointer to an object. 引用是指向对象的指针。

You can use "real" pointers in C# in unsafe code: here is an example 您可以在C#中以不安全的代码使用“真实”指针: 这是一个示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM