[C#] C# introductory study notes

Preface


        Hello friends, this article is the introductory learning knowledge of C#, including the author’s understanding and experience in the C# learning process.

        It took a week to compile this note, which can be collected and used as a  "key point"  for actual development . Since the content does not include the basic features and basic syntax of the traditional C language itself, this article is more suitable for students with a C/C++ foundation. Or friends with C# experience can conduct self-examination.

        If you are interested in C/C++, or want to know the general learning route before learning C#, you can refer to my other blog post: " I want them all! C, C++, C#!" Painless learning experience sharing》

Summary of difficulties for beginners


The following content is a bit difficult for me to learn when I was a beginner, so I have selected it for you. It is recommended that students focus on:

        5. Command line input and output : Write related content

        6. Data format conversion: Parse method, convert the string into the corresponding type (easier to forget)

        9. Two-dimensional array (C# is different from C/C++ in representation)

        11. Value types and reference types

                "Xiaochou x1" will not call the constructor, only "Xiaochou x1 = new Xiaochou()" will

        14. Variable length parameters params keyword function

        21. Member variables of "only external acquisition, no external modification" - member attributes (enhanced version of member variables)

                In this chapter, we should pay attention to the difference between name and Name member variables, which will be reflected in the text of the article.

                name: protected ordinary member variable

                Name: Externally accessible member attribute "interface"

        23. Indexer (belongs to advanced syntax)

                 public Person this [int index]

        27. Extension methods

    static class Add {
        public static int IntAddOne(this int thisval) {
            return thisval + 1;
        }
    }

               Among them, there are static requirements for the Add class, and public static requirements for IntAddOne.

               Among them, this int, int is the extended class, and any variable name can be chosen.

        29. Partial class: partial, divide a class into several parts and declare partial class Person

        36. Sealed class/abstract class

     


Environment setup

1. New projects

        The author is using VS2019, and the actual version 2015 or above is also compatible with the content of this article.

        Enter modification, install .NET desktop application → .NET SDK, and then open VS2019

2. Create projects under the new solution

        Note that this is not a new item=.=

        It's a new project! project! Multiple projects can be created under each solution

         Enter the following sample program, run it and display HelloWorld, then the environment configuration is complete.

Note text


1. Learn the two most basic shortcut keys - shortcut annotation

        ctrl K+C Comment

        ctrl K+U to comment

        F12 jumps to the declaration of function/class/namespace

2. Understand code blocks, function blocks and namespaces

        This code is used to output Hello World

        A toolkit System is referenced, where System is passed:

namespace System{ ... }

        A huge toolkit defined in this way contains declarations of functions that come with various systems.

3. View the definition of a function or class (F12)

        When we want to view the definition of a function or class, we can select it and press  F12  to jump.

4. Region (folding of code blocks)

        Using the region directive, you can fold a piece of code into an independent region, which can contain multiple code blocks, such as class definitions, properties, methods, etc. In Visual Studio, you can collapse or expand a region by clicking the minus sign on the left, or you can use the shortcut Ctrl+M+M to toggle the collapsed state of a region.

5. Input and output

    Console.WriteLine("Hello World!");
    string sin = Console.ReadLine();       // 等效于 cin  <<
    Console.WriteLine("OK");               // 等效于 cout <<
    Console.ReadKey();        // 监听一个按键消息。如果有任何按键立刻释放阻塞
    Console.WriteLine("   Detected.");

6. Data type conversion

        The essence of data type conversion is not only to put data of the same length in different containers, but also to perform it according to the range and precision requirements of the data type. In C#, data types are divided into value types and reference types.

        Normally, value type data (such as  int, double, struct,  etc.) can be type converted directly. It is not recommended to use forced type conversion for reference type data (such as class, interface, delegate ), because the result of the conversion may cause a null pointer. The standard conversion method is to use container as to other types, which you will learn in the subsequent advancement process.

        Specific conversion method:

        Implicit conversion: A default conversion automatically implemented by the compiler.

        Show conversion:

                1) Forced transfer, the same as the C language forced transfer method (less commonly used in C#)

                2) Parse method, convert the string into the corresponding type

                Syntax: vartype.Parse("str"), eg: int.Parse("123");

            string inp = Console.ReadLine();      // 等于 cin
            Console.WriteLine(inp);
            Console.WriteLine("result is:" + (int.Parse(inp)+1));
            //输入123字符串,Parse成int,返回这个输入数+1的结果

                3) Convert method, a universal method, can convert more accurately and can also round.

                Syntax: Convert.ToXXX(data)

                Conversion between string and other types:

            string i = "6";
            int a = Convert.ToInt32(i);
            Console.WriteLine("result is:" + a);

            float f = 1.233f;   //注意C#要求必须写f作为小数后缀
            string ret = Convert.ToString(f);
            Console.WriteLine("result is:" + ret);

                4) Convert other variables to strings: .ToString() method

            float f = 1.233f;   
            Console.WriteLine("result :" + f.ToString());

                You can even write:

                        1.ToString()

                This is because C# provides a simplified syntax for calling  ToString()methods

7. Exception catching

        the basic:

        In the following code, when the code in try executes abnormally, the try code will jump out and the catch code will be executed instead.

        Without using throw(), exceptions in try will generally not cause the program to shut down abnormally.

try{
   这里写我们要执行的
}
catch{
   这里写如果异常,那么捕获异常的代码
}

        Further, we can use advanced exception catching code. When an exception occurs, exception e can be caught, and the programmer can decide whether to print it out or save it in the log.

try{
   这里写我们要执行的
}
catch(exception e (用来捕获异常内容)) {
   这里写如果异常,那么捕获异常的代码
   throw;      // 加上这句的效果是异常发生的时候抛出。
}
finally{
    这句对不对都会执行,初步使用可以不用 finally
}

8. String splicing

1) Automatic conversion rules: If a string+int appears, this int will automatically Tostring

        str += 1; //No error is reported, the result is 1 added after str

2) String concatenation rules

        str += " " + 1 + 2 + 3; //The result is 123

        str += 1 + 2 + 3 + " "; //The result is 6

        str += 1 + 2 + " " + 3; //The result is 3 3

The reason is that the right side of the operator is calculated first, and the completed part will be type merged. X+string is merged into string type

3) Format splicing

        string str = string.Format("I am {0}, I am {1} years old this year", a, b);

9. Definition of one-dimensional array and two-dimensional array

        The format defined in this part is relatively flexible, and it is recommended that you only master one of the five methods.

        One-dimensional array:

    int[] arr1 = new int[] { 1, 2, 3 };
    int[] arr2 = { 1, 2, 3, 4 };
    //这两种都可以,感觉比较自由,注意不用C风格就好了

        Two-dimensional array: (note that you can only use new to pre-allocate space)

    int[,] arr2 = new int[2,2];
    arr2[0,0] = 1;

        C# adopts a different form from C and C++ in the definition of one-dimensional and two-dimensional arrays, mainly to provide better type safety and readability, and to simplify the syntax.

10. Get the array length

    // 获取数组的个数
    int[] arr = new int[] { 1, 2, 3 };
    int len = arr.Length;
    // 获取数组某个维度的个数,入参dimension,一般用于高维数组的kkjk
    int[] arr = new int[] { 1, 2, 3 };
    int len = arr.GetLength(0);

11. Value type and reference type of variables

        Value type : basic data type + structure, the value type is stored in the stack space, and its role in memory is equivalent to a "room"

        Reference type : class + array. Saved in heap space, its role in memory is equivalent to "house number"

                The reference type variable is after arr2=arr1, because the operation is "address reference"

                When arr2[x] is changed, if you read arr1 again, you will find that it has changed.

                This is because the specific memory being operated on is an address .    

        Special reference type: string

        In fact, in terms of usage experience, it is okay to think of string as a value type.

        When declaring the string type, the system will automatically allocate a string container with a temporary variable, so you don't have to worry about the house number.

12. VS debugging and breakpoint core skills        

        What should I do if I encounter a problem? You can use the debugging function to look at the memory step by step.

        The debugging function is relatively large. For beginners, we only learn to use the simplest method.

        Debugging four steps: 1) Set breakpoints 2) Run 3) Focus on the auto/watch window in the lower left corner 4) F10 step by step


 

13. Function operations of reference variables

        In the following function in C#, since the array is a reference rule, the result will actually change as an input parameter (this is very different from C/C++ intuitively, but in fact the internal reason is the same)

// Change函数
static void change(int[] arr)
{
    arr[0] = 233;
    return;
}
...
int[] arr1 = { 1, 2, 3 };
change(arr1);
//这个操作的结果是会把 arr1 的首项值 = 233;
      

        Essential principles:

 Figure - Parameter passing process of reference type

        When I first started learning, I found it hard to accept it! It has been verified that the value transfer type does not have this problem.

        Here is the validation code for value passing:

static void change(int[] arr) {
  arr = new int[] { 233, 233, 233 };  //不直接修改,而是new了一个!
  return;
}
...
int[] arr1 = { 1, 2, 3 };
change(arr1);

        Since arr is re-allocated to a new int[] space inside the function, the original relationship is destroyed.

        This is different from int *p = malloc(), but its internal design ideas are similar.

13. ref (out and ref, the usage of both is almost exactly the same)

        ref is equivalent to a reference to a function parameter in C++, equivalent to &. It should be noted that ref must be added to function definition and use. eg:

static void change(ref int value)

{

value = 233;

return;

}

...

int origin = 0;

change(ref origin);

        The difference between ref and out: the incoming variable of out must be assigned internally, which means that the function will modify the value of the out parameter by default.

        ps: If you want to use out, you must change it; the ref variable must be initialized.

14. Variable length parameters params keyword function

        Must be an array type. Note

        int func(int a, char b, params int[] c)

        Then there can only be one params and it is placed at the end.

15. Overloading has nothing to do with the return value type, only the parameters.

        If the input parameters are the same, there will still be an error even though the return values ​​are different.

        Note that ref int and int are two different input parameter types, but ref int and out int are one type.

        

16. Structures cannot be nested in C#, nor are nesting dolls allowed.

        Several points to note:

    1. C# structures can have constructors and destructors, but they must contain parameters, because no-parameter construction is generated by default.
    2. C# structures can be modified with private, etc. (scientific name access control character, default is private)
    3. Structures can use the this keyword to refer to the current object.

        Structure:

                MyStruct stu1 = new MyStruct { "qingxiu", 23 }; // This initialization method is not available

                MyStruct stu1 = new MyStruct {age=23}; // This is cool, please specify the attributes when assigning values.

                MyStruct stu1 = new MyStruct(); // This is also appropriate. Note that there is a () . It is easy for beginners to forget

17. Advantages of object-oriented

        Clear logical relationships, higher efficiency, reusability and development efficiency.

18. Three major characteristics of object-oriented (encapsulation, inheritance, polymorphism) and seven major principles (partial theory)

        This part has little to do with programming language learning. Interested students can search it by themselves.

        This part of knowledge is mostly summarized in the two courses of Software Engineering and Design Patterns , which are distributed at the undergraduate and graduate levels in domestic universities. Interested students can supplement this knowledge from MOOCs.

19. Content inheritance of parameterized constructors

        + :this() inherits the code of the parameterless constructor to complete reuse

        Similarly, it can be: parameterized constructor + :this(age+1) //Inherit the code of the parameterized constructor and customize the parameters.

        eg:

    class Person
    {
        private string name = "Default";

        public Person() {
            Console.WriteLine(this.name + " Created.");
        }

        public Person(string Name):this(){
            this.name = Name;
            Console.WriteLine(this.name + " Created.Append");
        }
    }

        The Person(string Name) constructor at the bottom will inherit the content in Person().

        The calling method is as follows:

                Person p1; // Note that this is just a declaration of variables and no new operation, so the constructor will not be called.

                Person p1 = new Person(); // Call the parameterless constructor

                Person p1 = new Person("blabla"); // Call parameterless construction + parameterized construction, because: this() is added above

20. Automatic garbage collection mechanism GC

        The definition of garbage: nothing that is referenced and needs to be recycled and released

        The process of garbage collection: traverse all objects allocated on the heap in each generation.

        Start saving from generation 1. If the current nth generation is full, GC will be triggered to recycle & rearrange the first 1~n generations.

        Specific mechanism:

        It is actually an application of multi-level priority feedback queue. GC uses the principle of locality. Eventually frequently referenced variables will be promoted, while large memory will be on generation 2 initially.

        Manually trigger GC: GC.Collect();

21. Member attributes

        Member variables that are “only acquired externally, not modified externally” (belonging to advanced syntax)

        Background: The 3P (private, protected, public) method is inconvenient to define a constraint outside.

                private: access only

                protected: only accessible by inner and inner subclasses

                public: internal and external access

                Then there is no such thing as "external access only". In order to facilitate flexible permission management, the need for member attributes has arisen.

        Some tips on member attributes:

        1) Key features: dedicated get{} and set{} for private member variables. These two things are called "accessors".

        2) value keyword: represents input parameters

        3) Only one of get and set can be implemented, and both can also declare access permissions.

        4) Get and set can be designed for applications such as encryption and access control.

        Basic operations:

    class Person
    {
        private string name = "Default";

        public string Name{
            get {
                return name;
            }
            set {
                name = value;    // value关键字:简化代表为入参
           }
        }
        ....
调用:
       p1.Name = "Yooo!";  
       Console.WriteLine(p1.Name); 

        Extended Operations: Storage Encryption

get{
    return name - asdafs;    // 这样在内存里就找不到存入的值了
}
set{
    name = value + asdafs;    
}

        Extended operation: Set the access permission of the variable to [only allow external access, not modification]

public string Name{
    get{
        return name;
    }
    private set { }
}
或者简写为:
public string Name
{
    get;
    private set;
}

        Effect:

22. How to express "a Person's Person's friends"?

It can be represented by the following code:

class Person{

        private string name;

        private Person[] friends;

}

23. Indexer (belongs to advanced syntax)

        Allowing class objects to access elements like an array is conceptually similar to overloading "[ ]"

        Note that this is about concepts. In fact, C# does not support the overloading of square brackets, and it cannot be overloaded as extensively as C++.

    class Person
    {
        public string name = "Default";
        private Person[] friends;

        public Person this[int index]
        {
            get {
                return friends[index];          // p[0]:定义为第一个朋友
            }
            set {
                if (friends == null) {
                    friends = new Person[10];
                    friends[0] = value;         // value:入参
                }
            }
        }
   }
   
   调用方法:
            p2.name = "Amy";
            p1[0] = p2;           // 将p1的第0个朋友设置为 Name="Amy"的人

tips:

        1) public Person this [int index] // This format is a fixed combination: public return type this [params]

        2) public Person this [int index, int age] //The indexer can be overloaded

24. Static member static

        The more essential understanding of the keyword static in C# can be said to be "putting the corresponding members into the static area so that they can be loaded at the beginning of the program startup . "

        If the reader happens to have studied operating systems, you can also think of static members as members that "memory has been allocated at the beginning of the program running" . The reason why it can be understood is that after static members are read and loaded, they cannot be operated dynamically, nor can they be recycled through GC.

        In fact, the instantiated object does not have static members. The owner of the static members is the class in which they are located. We usually use these variables directly by naming them without instantiating the object!

        Static variables will allocate memory space directly by the program when the program is running. They live and die together and have a full life cycle.

        Characteristics of static variables: 1) globality 2) direct "." access 3) always in a specific memory segment when the program is running.

        eg: In class TestClass, you can have the following variables:

                1)

                Static member variables: static public float PI=3.1415926f; can be TestClass.PI

                Ordinary member variables: public float PI=3.1415926f;

                2)

                Static member method: static public void TestFunc(); can TestClass.TestFunc()

                Ordinary member method: public void TestFunc();

        Note: In static Func(), ordinary member variables cannot be used (very important, you must understand the principle). Because static Func() has its own memory when the program is running, and ordinary member variables must be instantiated before being allocated memory. Therefore, it is the life cycle problem that leads to this feature. If you really want to use it, instantiate a new one first.

        Likewise, static variables will not be GCed! Static allocation will always occupy memory. Use static with caution when allocating large blocks of memory.

        The functions of static variables: 1) often used for unique quantities 2) want to bypass instantiation for others to use

        Typical examples of static methods: 1) will not be changed and define unique mathematical formulas, etc.

25. const is a special kind of static

        have many of the same properties

26. Static class:

        1) Not instantiable

        2) Unique

        3) Static constructor: called when used for the first time and no longer called after that

        eg:Console

27. Extension methods (useful! Must be public & static)

        Existing methods in a non-static class can be externally extended

        For example, you can add your own method to the Int32 class.

        Features: It must be a static function in a static class, and the first parameter is modified by this

class Person  // 其中Person类没有任何除构造以外的成员方法   
 {}
 
// 定义扩展方法
static class AddFunc
{
                            // 意在对 Person 进行扩展
    public static void Func(this Person obj, int val)
    {  // obj:名字可以乱起,调用时是自动传入的,代表实例化的对象
        Console.WriteLine("AddFunc:" + val);
    }
}

// 调用
Person p1 = new Person();
p1.Func(233);

        In C#, extension methods must be declared static to work properly. This is because an extension method is a static method that does not depend on a class instance, but is a method that can be used throughout the application.

        In short, this method can be used directly without creating an instance of the class, such as: 1.ShowIntValue();

        The 1 here does not require us to perform new int operations, it can be used just as it is. And it is used throughout the exe.

28. Operator overloading (Must be public & static)

        Note that operator overloading must set the overloaded method to static within the class and have a return value.

        The following code example adds an addition rule to two-digit numbers (x,y):

class Point //
{
    public int x;
    public int y;

    public static Point operator +(Point p1, Point p2)  //记住格式!
    {
        Point temp = new Point(0, 0);
        temp.x = p1.x + p2.x;
       temp.y = p1.y + p2.y;
       return temp;
    }
    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

//调用如下:
 Point po1 = new Point(1, 1);
 Point po2 = new Point(3, 4);
 Point po3 = po1 + po2;

 Console.WriteLine("{0}, {1}", po3.x, po3.y);

        C# cannot be overloaded: [ ] && || . ?: () =

        In C#, you can implement multiple operator overloads for a class, including new operators. However, in order for these operator overloading to take effect, you must ensure that they are declared public and static.

        The reason for using public is to ensure that these operator overloads can be accessed and called by other classes. The public access modifier tells the compiler that these operators can be accessed from anywhere, not just from within the class. If the operator is not public, it can only be accessed from within the class, which will cause compilation errors.

       The reason for using static is to ensure that these operator overloads take effect. The static access modifier tells the compiler that these operators are not instantiated, but are class-level operators that can be used throughout the application. If the operators are not static, then they can only be used inside the class, which will cause compilation errors.

        How to understand it? It's actually very simple. We use p1+p2 instead of incorrect forms like p1.+() and p1.+.

        Obviously, the writing method of p1+p2 does not belong to the usual dot method for chain calls.

        This feasible premise of p1+p2 must be supported at the beginning of the program running.

29. Internal classes and partial classes

        Inner class:

        Call: Person.Body.ShowBody();

        ps: It is a class within a class, making the affiliation between the two classes more intimate.

class Person
{
    public string name = "Default";
    private Person[] friends;

    public class Body{
        public static void ShowBody(){
            Console.WriteLine("ShowBody.");
        }
    }
}

        Branch category:

               The keyword is partial, which means dividing a class into several parts and declaring it

               Belonging to different modular subsystems, then it has to be like this.

               Anyway, someone in the barrage said this is very useful, so mark it first.

    partial class Person{
        public string name;
        public int age;
    }

    partial class Person {
        public string nation;
    }

30. Inheritance

class PersonMan : Person {

        public string nation;

}

        C# inheritance: can only have one parent class; C++ inheritance can have multiple parents;

        So there is a joke. In C++, you can have: class Lu Bu: Ding Yuan, Dong Zhuo

31. Richter substitution principle

        Anywhere a parent class appears, a subclass can replace it. An excellent design should be: use a parent class container to load subclass objects.

        eg:

        Person p1 = new Student();

        Person p2 = new Teacher();

        eg:

GameObject[] objects = new GameObject[] { new Boss(), new Monster() ,\
                                          new Player() };   
遍历这个数组,可以用is和as来进行不同类型的对象的处理。 

        is and as : type checking and conversion of objects (serving the Liskov substitution principle)

        is: (return value is bool type)

                eg: if (p is Player) ...

        as: (return value: returns the specified type object if the conversion is successful, returns null if the conversion fails)

                eg: Player p = object as Player

        Routine operation - use both together:

// 前置定义 
    class PersonMan : Person{
        public int len;
    }
    class PersonWoman : Person{
        public int dep;
    }
 
Person p1 = new PersonMan() { name = "A", age = 18, len = 18 };
Person p2 = new PersonWoman();

if (p1 is PersonMan) {   // 判断p1是否属于PersonMan类,如果是,则...
    PersonWoman p3 = p2 as PersonWoman;    // 令p2转换成PersonWoman类型
    Console.WriteLine("Show:" + p3.name + " " + p3.dep);  
}

        If the converted type is the same as the target type, the conversion is successful. When Person has a subclass PersonMan, a PersonMan is both a PersonMan and a Person

32. Constructor in inheritance

        First call the parent class constructor, then call the subclass constructor

        Since the default call is the parameterless constructor of the parent class, it is agreed that the parameterless constructor of the parent class must exist! (Because the default is to find a no-parameter construct)

        If you want to call the parameterized constructor by default, you need to use the base keyword. At this time, the parameterless constructor of the parent class is not allowed to be declared.

        eg pseudo code:

        class {

                func(): this (can pass parameters) // Find the constructor with corresponding parameters

                func(): base (can pass parameters) // Find the parent class constructor of the corresponding parameters

        }

// 申明类和构造函数
        class Father
    {
        public Father() {    // 默认调用的无参父类构造函数
            Console.WriteLine("Father NULL");
        }
        public Father(int i) {
            Console.WriteLine("Father:" + i);
        }
    }

    class Son : Father
    {
        public Son() { }
        public Son(int i) : base(i)  //base是Father(),base(i)是Father(i)
        {
            Console.WriteLine("Son: i");
        }
        public Son(int n, int m) : this(n)  // this(..) 都是指自己的构造
        {
            Console.WriteLine("Son: n, m");
        }
    }
// 调用:
        Son s = new Son(2, 3);  
        
--控制台打印结果:
Father:2
Son: i
Son: n, m     -解析:new Son(int, int) 的操作:1、先构造父类
                                              2、再构造 this(int)
                                              3、最后构造自己

33. Inherited construction call relationship

        In short, it means starting from the ancestors and gradually calling the descendants.

34. The most basic base class: object (reference type).

        Since the object object is a reference type, it is designed to be a container that can hold any type of object.

        Note: object cannot be forced or as, such as: object w = (Son)f; This syntax is correct, but it will cause problems.

    object val = 1.23f;       // 装箱
    Console.WriteLine(val);   
    float v = (float)val;     // 拆箱

        Reference type: It is recommended to always use as to convert, rather than force conversion:

                object NewArray = new int[10];

                int[] ar = NewArray; // This code will report an error because the object type cannot be implicitly converted to the int[] type.

        This should be done:

                object NewArray = new int[10];

                int[] ar = NewArray as int[ ]

        Here is a little tip of my own:

        The difference between new and as: new must be used to allocate memory, while as is used to convert types

35. Packing and unboxing (what is the significance of object operation?)

        Value types are stored as reference types, and the storage location can be moved from the stack to the heap.

        Benefits: When the type is uncertain, it is convenient to store and convert parameters in advance

        Disadvantages: Memory migration brings performance losses

        eg: object [] can temporarily "eat everything" when you don't know what type the member is, and can be used to hold any type.

        However, it is better to use it as little as possible, because there are some problems with performance loss and design specifications.

36. Sealed class/sealed function, keyword: sealed

        Sealed class: Make the class no longer inheritable (cutting off descendants can ensure safety and standardization)

        sealed function: This function cannot be overridden (cannot be overridden)

37. Polymorphic classic solution:

        Background: We are trying to solve a problem:

    class Father{
        public void Speak() {
            Console.WriteLine("Father");
        }
    }
    class Son : Father{
        public new void Speak()    
        {
            Console.WriteLine("Son");
        }
    }

        When making the following statements, there will be different performances:

Father s = new Son();
    s.Speak();           // 执行Father的Speak函数,因为使用的是Father容器
    (s as Son).Speak();  // 执行Son的Speak函数

        This caused some problems for inheritance. In order to avoid inheritance being logical, we later introduced virtual, overide

        virtual virtual function : used to override subclasses.

        override : declare override, and then when completing this function, it can be automatically completed into a subclass override function with base.Speak().

    class Father{
        virtual public void Speak() {
            Console.WriteLine("Father");
        }
    }
    class Son : Father{
        public override void Speak(){    
            base.Speak();   // base代表父类,可以用base保留父类的行为
        }
    }

transfer:

        when we proceed again

        s.Speak();

        During this operation, although s is still using Father's container, its Speak function has been overridden, so the Son.speak() method will be executed.

38. Another implementation method of polymorphism - abstract class: abstract modification

A general term for a class, such as: abstract class Things.

There is no class of things called Things in the real world, but we can inherit them through different classes in the future.

Doing this is like a "blueprint":

        1. Abstract classes are only responsible for declaring common properties and methods that should appear, but do not implement them concretely.

        2. Abstract classes cannot be instantiated.

eg:

    //抽象类
      abstract class Father{
          //抽象方法(只能写在抽象类里,且必须是public的,因为以后必须override)
        public abstract void Speak();   // 不用写函数体,类似纯虚函数
    }

39. Namespace namespace

        namespace has the following characteristics:

        1. Like a tool kit; in contrast, class is like a tool

        2. It can be written separately. For example, the previous sub-category can be written into several paragraphs.

        3. The namespace must be referenced or clicked through using, otherwise it will not be found even if it is in the same file.

        4. Can be nested:

                namespace toolkit {

                        namespace screw { ... }

                        namespace nut { ... }

                }

                When referenced, it can be: using toolkit.nut; using Game.UI

        5. The default namespace classes are internal (can only be used in assemblies), not private, please pay attention!


There are still some minor problems with the readability of the notes. I am currently rushing to update them, and I will definitely fix them when I have time!

Come on friends, let’s go owo

Guess you like

Origin blog.csdn.net/qingxiu3733/article/details/131498742