SoFunction
Updated on 2025-04-04

What makes C# grammar unique compared to other languages ​​(II)

A brother had a post on my post before. I didn’t have g, m at that time. He didn’t regret it until he deleted it. This is the most painful thing in life. . . . . .

OK, even so, we still run forward with hope. Then write Volume 2.

I also want to mention that the last delegate mentioned last time, after I understood its implementation and purpose and saw some access records of my idol, I have a deep understanding of it. In terms of event processing mechanism, I prefer my idol. Some brothers say that MFC is a switch and java is a listener. In fact, these listeners in Java are not switches and then called in processEvent, and they are all switches. Then switches cannot be said to be a feature. The biggest feature is whether to directly use function pointers to respond. Let’s talk about signal processing again. The previous 8259A interrupt check interrupt vector table also ends with address transfer. This is not a feature. Later calls are all address transfers, and the difference in speed lies in the fact that there are certain implementations of the same level, and the efficiency differences caused by different mechanisms and architectures are all determined by strength.

1. Internal and protected, private

By default, when defining a class, if you do not add any access modifiers, the access permissions of the class are internal, of course you can explicitly formulate them as internal. What is internal? Internal means that in the current project, it can be accessed, no matter how many namespaces you use, it doesn't matter.

However, when defining a member variable in a class, if you don't write anything, the default permission of this member variable is private. If you want this member to be accessible in the current project, you must use the internal keyword to explicitly modify it.

In addition, the protected access permissions in C# still have the same meaning as in previous C++, indicating that only the inheritors have access permissions. Even for the same project and other classes in the same namespace, you can't see this protected member, which is quite strict access restrictions.

Internal and protected basic control access is in different fields, and they can be used to modify an object at the same time. for example

Copy the codeThe code is as follows:

    class PPP
    {
        internal protected static int c=3;

    }


There is no intersection, nor is there mutual exclusion.

This is completely different from Java. In fact, I could not mention Java at all, but due to my own background and a comprehensive summary, I still took out Java and compared it with C#. After all, the title of this article is "special". Of course, I don't know if you think it is C# or Java.

There is no access control exactly the same as this internet in Java, it has a unique package access control. Whether it is a class or a member of a class, if you do not write access modification, then it is at the package access level. The meaning of the package access level is that it can be accessed in this package. There is no such level in Java that can be accessed in the "in this project" or this "jar" similar to the internal one, only the package level.
The protected in java is also much more tolerant than the protected in c#. The meaning of protected in java is actually equivalent to the protected in c# and the package in java. Someone made an example, saying that there are many resources in the big house gate that are protected. These resources can not only benefit the neighbors (in the same package), but also give them to their own sons and grandsons (sons and grandsons obtain resources through inheritance) even if they go far away.

2,enum

We have learned that when defining element symbols in enums in C. This symbol cannot be the same as other symbols in the current scope. Moreover, all these symbols in enums can be used directly as constants, just like #define a plastic constant. Especially when not setting up enum type tags, it's simply a #define.

The difference is that when defining an enum object like this, it is not necessary.
Write enum type tag object;
And just write the type tag object;

It's like before I had to write a struct type tag object;

In C++, you can only write type tags; the same thing, but whether in C# or Java, first of all, they cannot omit type tags. Secondly, it is not necessary to ensure that other tags must be different from the same scope. Furthermore, you cannot directly use the element symbols in the enum as constants. At least you have to write type marks and element symbols.
for example

Copy the codeThe code is as follows:

enum XXX{A,B,C,D}
....
();

But there is something special about C#, which retains some of the functions that only C enums have. That is, operators + and - can be used to operate on enum objects. This is absolutely impossible for Java to do, and it can also be converted back to the int type. for example
Copy the codeThe code is as follows:

enum weekdays{sunday,monday.....saturday}
for(weekdays wd=;wd<=;wd++)
   ...
(int)   //The result is 0

Can also assign values
Copy the codeThe code is as follows:

enum open_modes{
  intput=1,output,append,
  last_input_mode=input,last_output_mode=output
}

If you think the default implementation is int type too consumed, you can use the byte type
Copy the codeThe code is as follows:

enum weekdays:byte{
....
}

Can==
We all know that the Equals method can override people to judge whether two objects are of the same value, and == can only compare whether the refs of the two objects are equal.

In Java, we use "hello".equals(aaa);
However, in C#, the == operation of the string object has been forcibly rewritten, which means equals.
This means that in C#, if you implement string value comparison, you only need to write "hello"==aaa.
The purpose of this design is to be more intuitive.

4. Pass the quote

There is a very classic question in Java, and the visit of this question really makes me accustomed to it.
That's the problem with string processing functions.
In java or c#, someone

Copy the codeThe code is as follows:

void processString(String a)
{
    a=a+"asdfjsdf";
}

Or digital exchange problem
Copy the codeThe code is as follows:

void processInt(int a,int b)
{
  int temp=a;
   a=b;b=temp;
}

The former also says something, while the latter has not even laid a foundation for C. For the latter, it is recommended to go to tutor C.
Let me talk about the former. Whether in Java or C#, the string object is immutable, that is, once it is generated, it cannot be changed. So what does the + operator do? It will generate a new string object and then fill in the contents of the string on both sides.

In other words, a+"asdfdjkf" is a brand new thing. If written as a+="asdfj" or a=a+"sdfjk", then the original a and this "asdjf" can be GC.

Let’s talk about the object types in java and c#. All object types in java and c# are ref types, that is.

Copy the codeThe code is as follows:

String a;

In this sentence, it just defines a ref. It basically does not occupy any resources and does not generate any real objects. It is just a ref.

When String a="dkfjsdf";, an object "dkfjsdf" is generated on the controlled heap, and then the ref of this object is returned to a.

Let's look at the string processing just now. A is just a formal parameter similar to a local variable. You set the ref of a to a new value, and then the function returns, the formal parameter a is gone, and the original actual parameter has no changes.

But you said, I just want to deal with it this way, what about doing? In Java, it is impossible to handle String like this, but StringBuffer and other things are OK, because although we cannot change the ref value of the actual parameter, we can change the internal members of the object through the same value ref. We have no choice for immutable, but we can pinch the mutable.

And in C#, very congratulations on your success. It is OK to deal with strings as we just imagined, but it is necessary to do so.

Copy the codeThe code is as follows:

void processString(ref string a)
{
  a+="sdjkf";
}

Adding ref will cancel the generation of formal parameters and the repression of the stack, just like string & in c++, which is equivalent to giving you the actual parameters directly.
In this way, we can do whatever we want to do, so that our processString will succeed.
However, when filling in the actual parameters, you need to write it like this
Copy the codeThe code is as follows:

string h="haha";
processString(ref h);
(h);

We can see that h is changed.

5, out parameter

The out parameter is like directly implementing the semantics of out in the com interface definition through the C# language.
It is the output parameters. We know that whether it is Windows API or com, the return value of the function is usually used to handle exceptions, and the real result is brought back through the output parameters. There are many ways to implement the output parameters, such as passing the address and passing the reference. Of course, the weird reference in C++ is never used in com.

The only difference between the out parameter and the ref parameter we mentioned before is that the ref parameter must be initialized before filling in the actual parameter, but the out parameter does not require this. It is used to bring back the result. You can define an uninitialized local variable, and then fill it in it in the out variable name. After the call is completed, the value will be placed in this variable.

For example, we changed the processString just now to explain the usage of out parameters.

Copy the codeThe code is as follows:

void processString( out string a)
{
   a="xxx";
}

string a;
processString(out a);
(a);