Better coding-luminjis web
Current topic:
1: use attribute or field
The first major difference is that the attribute is actually a method, so:
1: You can add code for attributes;
2: attributes support thread security. For details, see chapter 1 of Objective c # The first version;
3: attributes are supported by the VS editor to enable automatic attributes.
4: the features of automatic attributes have been widely used in LINQ, especially for anonymous types. Only read-only automatic attributes can be implemented, but fields are not supported for anonymous types;
5: from the design perspective, that is, the object-oriented perspective, we recommend that you use attributes;
6: if an attribute is used only within the type and does not involve the preceding five points, we recommend that you use fields.
Another point is that attributes are a bit embarrassing in serialization. Because attributes are methods, you cannot specify the [NonSerialized] attribute for them.
2: broaden the application scope of the Method Using Generics
Suppose there is a method:
Static void PrintSalary (ISalary <Employee> s) {s. Pay ();}
Then use it as follows:
ISalary <Programmer> s = new BaseSalaryCounter <Programmer> (); PrintSalary (s );
Note: code for several main classes:
Interface ISalary <T> {void Pay ();} class BaseSalaryCounter <T>: ISalary <T> {public void Pay () {Console. writeLine ("Pay base salary") ;}} class Employee {public string Name {get; set ;}} class Programmer: Employee {}
The running result is:
Cannot be converted from leleapplication4.isalary <ConsoleApplication4.Programmer> to ConsoleApplication4.ISalary <ConsoleApplication4.Employee>"
Obviously, because the PrintSalary method supports ISalary <Employee>, it is certainly supported by ISalary <Programmer>, which is a very easy attempt.
The improvement method provides an idea to change this method to a generic one.
3: Use the covariant keyword out
To solve the problem in topic 2, you can also use the out keyword. That is, modify the interface:
Interface ISalary <out T> {void Pay ();}
4: reduce the use of static variables
1. Once a static variable is created, it cannot be released;
2: static variables are not thread-safe. They are not only valid for the thread of the Creation type;
5: How many methods does thread synchronization work?
The technology used for thread synchronization is to wait on an object (also known as locking the object ). Class of type objects in C #: reference type and value type. The waits for these two types are different. We can also simply understand that in CLR, the value type cannot be locked (refer to the volatile keyword of MSDN ).
There are two types of wait on the reference type: Lock and signal mechanism.
Lock usage: keyword lock and type Monitor. The former is actually the syntactic sugar of the latter. This is the most commonly used synchronization technology, which should have been used by developers;
Signal mechanism: All types involved in the signal mechanism are inherited from the abstract class WaitHandle. These types include EventWaitHandle (converted to AutoResetEvent, ManualResetEvent), Semaphore, and Mutex. There are some differences between them. It is worth mentioning that Mutex can synchronize different application domains. The other several types of differences are very hurtful in MSDN, and there is no horizontal comparison. In short, EventWaitHandle synchronizes data through the boolean type. In this case, AutoResetEvent automatically restores the block state of the type, manualResetEvent must be restored manually. Semaphore synchronizes data using integer data.
6: Can an object = null be accelerated to be recycled by the garbage collector?
Note that the following descriptions only apply to the reference type
1: In a method, if the value of the method parameter and local variable is null, the garbage collector does not help to identify the method as garbage;
2: instance variable. With instance = null, the instance variable is automatically = null. Therefore, generally, you do not need to explicitly set instance variable = null unless your instance has a long life cycle and the instance variable is a large object;
3: static variables. If they are not explicitly set to null, they will never be recycled;
7: it is not recommended to lock (this)
1: If the instances of the two objects Execute Code such as lock (this) respectively, the actual lock is two objects, which cannot achieve synchronization.
2: it is best to avoid locking the public type or locking an object instance that is not controlled by the application. For example, if the instance can be publicly accessed, lock (this) may be faulty because uncontrolled Code may also lock the object. This may cause a deadlock, that is, two or more threads are waiting to release the same object. For the same reason, locking public data types (compared to objects) may also cause problems.
8: differentiate computing-intensive and I/O-intensive multi-thread application scenarios
I/O-intensive operations. Hard Disk, Nic, sound card, and video card. The asynchronous programming model provided by CLR enables us to make full use of the hardware DMA function to improve CPU utilization.
A correct technique in most cases is that any type of FCL that provides a method similar to BeginDoSomething is recommended to use this asynchronous call to complete multi-thread encoding, asynchronous scheduling is completed by calling the thread pool thread in the background, which maximizes system performance.
9: a trap of using Parallel
What is the output of the following code?
Int [] nums = new int [] {1, 2, 3, 4}; long total = 0; Parallel. for <long> (0, nums. length, () =>{ return 1 ;}, (I, loopState, subtotal) =>{ subtotal + = nums [I]; return subtotal ;}, (x) => Interlocked. add (ref total, x); Console. writeLine ("The total is {0}", total );
In fact, it may be 11, but in a few cases it may be 12, and it is almost impossible to appear.
Starting from the last parameter Action <TLocal> localFinally of the method, it indicates that if a new thread is created in parallel, the localFinally will be called at the end of the thread. We know that parallel execution uses a thread pool in the background, that is, we do not know how many threads will be initiated by the parallel execution initiated by the code above, if it is one, naturally, it is 11. If it is 2, the result is 12, and so on. The reason why it cannot be 14 is that the concurrent loop body has only four loops, and the concurrency is obviously not stupid enough to start four new threads to execute the concurrency.
10: it is not recommended to lock (type)
Because typeof (SampleClass) is shared by all instances of SampleClass, this will cause all threads of all SampleClass instances in the current application to be synchronized.