50 suggestions for improving C # programming (21-25)

Source: Internet
Author: User

21. Restricted type visibility
Not all types require Public. You should give you the least visibility of the type to achieve your goal, internal or private classes can implement public interfaces. Many independent classes should be created internally. You can use protected or private Nested classes to further limit the visibility of the system. The smaller the visibility, the fewer changes the system will make when you update the system later, the less you access your code, the less you modify.
Expose only those that need to be exposed. For classes with low visibility, try to expose them using public interfaces.

// For illustration, not complete sourcepublic class List
 
   : IEnumerable
  
   {    private class Enumerator
   
     : IEnumerator
    
         {        // Contains specific implementation of        // MoveNext(), Reset(), and Current.        public Enumerator(List
     
       storage)        {            // elided        }    }    public IEnumerator
      
        GetEnumerator() { return new Enumerator
       
        (this); } // other List members.}
       
      
     
    
   
  
 

The client code does not need to know the Enumerator of the class. .
. NET many collection classes are also designed like this, such as Dictionary Contains private DictionaryEnumerator , Queue Includes QueueEnumerator .
Creating an internal class is a method that is ignored to limit the type range. By default, most programmers always create Public classes without considering anything else, because these are all done by the VS. NET wizard. When receiving the default form, you should pay attention to where your new class will be used? Are all clients or are they mainly used inside the assembly?
Using Interfaces to expose your functions makes it easier to create internal classes, such:
public interface IPhoneValidator{  bool ValidateNumber(PhoneNumber ph);}internal class USPhoneValidator : IPhoneValidator{public bool ValidateNumber(PhoneNumber ph){  // perform validation.  // Check for valid area code, exchange.  return true;}}


22. Preference for defining and implementing interfaces rather than inheritance
Abstract base classes provide class-level ancestor. An interface describes an atomic function that can be implemented by a class.
Interfaces are designed in a contractual manner: a class that implements interfaces must provide an expected method implementation. Abstract base classes provide a public abstract method for a series of related types. Inheritance refers to what interfaces mean by behaviors. These are common issues, but they also work. They describe two different concepts: the base class describes what the object is, and the interface describes a behavior of the object.
Interface describes a set of functions or a contract. You can create methods, attributes, indexers, and events in the interface. You can also create methods not available for interfaces. Because methods do not have specific data members, you can use extension methods to expand interface functions. For example, extended generic interface IEnumerable :
    public static class Extensions   {public static void ForAll
       
        (this IEnumerable
        
          sequence,Action
         
           action){foreach (T item in sequence)action(item);}   }        // usagefoo.ForAll((n) => Console.WriteLine(n.ToString()));
         
        
       

Abstract base classes can provide some common implementation methods for Their Derived classes. They use virtual methods to specify data members and specific methods for the derived classes. This base class implementation brings the following benefits: if you add a method to the base class, all its derived classes are automatically and implicitly added. however, adding a method to the interface will lead to errors in all classes that implement it. selecting an abstract base class or an interface involves how to always support your abstract functions. the interface is always fixed: You issue an interface as a contract for a series of functions that can be implemented by any class. the base class can always be extended. these extensions will also become part of their derived classes.
The two models can be used together. An example is IEnumerable In the. NET Framework. The interface and the System. Linq. Enumerable class. System. Linq. Enumerable class contain System. Collections. Generic. IEnumerable Interfaces.
The interface can be implemented by any number of irrelevant types. Writing interfaces provides developers with great flexibility to write basic classes. Because the. NET environment only supports single inheritance, and the interface solves the problem of multi-inheritance. The interface also allows you to occasionally reduce the cost of the structs type unpacking. For example:
public struct URLInfo : IComparable
         
          , IComparable{    private string URL;    private string description;    #region IComparable
          
            Members    public int CompareTo(URLInfo other)    {        return URL.CompareTo(other.URL);    }    #endregion    #region IComparable Members    int IComparable.CompareTo(object obj)    {        if (obj is URLInfo)        {            URLInfo other = (URLInfo)obj;            return CompareTo(other);        }        else            throw new ArgumentException(            "Compared object is not URLInfo");    }    #endregion}
          
         

Any IComparable-based code will reduce packing and unboxing, because the IComparable. CompareTo method can be called Without disassembling objects.


23 understand the differences between interface methods and Virtual Methods
At the beginning, we thought that implementing an interface is the same as rewriting a virtual method, but actually implementing an interface is very different from rewriting a virtual method. first, the member methods in the interface are not declared as virtual by default. A derived class cannot override the implemented interface members in the base class. The interface can display the implementation to hide the public interfaces inherited from the class. They are different concepts for different purposes.
You can modify the implementation of the interface in the derived class. For example:
interface IMsg{    void Message();}public class MyClass : IMsg{    public void Message()    {        Console.WriteLine("MyClass");    }}
The Message () method is now a public interface of the MyClass class. Message can also be accessed through the IMsg pointer. Now we will add a derived class:
public class MyDerivedClass : MyClass{    public void Message()    {        Console.WriteLine("MyDerivedClass");    }}

Because MyClass. Message () is not virtual, the derived class cannot provide an overwritable Message () version. In this case, the derived class creates a new Message () method, which hides the Message () method of the base class, which is equivalent to the new void Message () method (). Using IMsg to reference MyClass. Message is still usable:
MyDerivedClass d = new MyDerivedClass ();
D. Message (); // prints "MyDerivedClass ".
IMsg m = d as IMsg;
M. Message (); // prints "MyClass"
When you implement an interface, you actually declare the specific implementation of a special contract in the class. But we usually want to create and implement interfaces in the base class, and then modify it in the derived class:
    public class MyClass : IMsg    {        public virtual void Message()        {            Console.WriteLine("MyClass");        }    }    public class MyDerivedClass : MyClass    {        public override void Message()        {            Console.WriteLine("MyDerivedClass");        }    }

MyDerivedClass and all classes derived from MyClass can declare their own Message methods. This rewriting version can be referenced and accessed by a derived class, can be referenced by an interface, and can be referenced and accessed by a base class. If you do not like the concept of a virtual function, you can redefine the base class as follows:
Public abstract class MyClass: IMsg
{
Public abstract void Message ();
}
Yes, you can declare it as an abstract method without actually implementing an interface in the base class. In this way, all derived classes must implement this interface method. A derived class can seal this method to prevent its own derivation from rewriting it:
    public class MyDerivedClass2 : MyClass    {        public sealed override void Message()        {            Console.WriteLine("MyDerivedClass");        }    }

Another solution is to implement the interface and then include a method to call the virtual method, such:
    public class MyClass2 : IMsg    {        protected virtual void OnMessage()        {        }        public void Message()        {            OnMessage();            Console.WriteLine("MyClass");        }    }

Any derived class can override the OnMessage method and add their own work in the Message method .. NET event Methods almost all use this mode.
The base class can provide a default Interface Method implementation, and then the derived class can inherit the base class declaration and implement the interface method, such:
    public class DefaultMessageGenerator    {        public void Message()        {            Console.WriteLine("This is a default message");        }    }    public class AnotherMessageGenerator :    DefaultMessageGenerator, IMsg    {        // No explicit Message() method needed.    }

Note that the derived class can declare this interface as part of its own contract. Even if it does not provide the Implementation of The IMsg method, it implicitly implements this interface method by inheriting the methods of the base class.


24 use delegate to indicate callback
The callback function is used to asynchronously provide a feedback to the client from the server. They may involve multiple threads or simply provide an entry point for Synchronous updates. The callback function is represented by delegation in C.
The delegate provides a type-safe callback function definition. Although most events are used for delegation, this is not the only thing that can be used for delegation. Delegate allows you to configure the target at runtime and notify multiple clients. A delegate is an object that contains method references. The included methods can be static methods or instance methods. With delegation, you can communicate and configure with one or more client objects at runtime.
C # provides a compact syntax (lambda expression) to express the delegate .. The NET Framework library defines many common delegate forms, such as: Predicate , Action <>, and Func <>. predicate is a Boolean function used to test conditions. Func <> requires some numeric parameters and then produces a result. That is, Func And Predicate The format is the same. Action <> enter any number of parameters and return a void type. LINQ is built on these concepts.
List Class also contains many methods to Use callback functions, such:
List Numbers = Enumerable. Range (1,200). ToList ();
Var oddNumbers = numbers. Find (n => n % 2 = 1 );
Var test = numbers. TrueForAll (n => n <50 );
Numbers. RemoveAll (n => n % 2 = 0 );
Numbers. ForEach (item => Console. WriteLine (item ));
The Find () method receives a delegate with Predicate To test each element in the list. This is a simple callback. The List. ForEach () method executes the specified action in each List element. In fact, the compiler converts a lambda expression to a method, and then creates a delegate to point to the method. All the LINQ statements are built on the delegate. In WPF and Windows Form, callback is used to process cross-thread messages.
For historical reasons, all delegates are multicast delegates. Multicast delegates encapsulate all the target functions and add them to a single call. This construction has two problems: one is insecure in the face of exceptions, and the other is that the return value is the return value of the last target function call.


25. Event Notification
The. NET event mode is nothing more than a syntax conversion of the observer mode. Events define notifications for your class. The event provides a type-safe function Signature Based on the delegate.
Consider a simple example. You have created a log class, which is a scheduler for all messages of an application. It receives all the messages from the application and schedules these messages to the listener interested in the application. These listeners may be attached to the console, database, and system logs. The definitions are as follows:
public class LoggerEventArgs : EventArgs    {        public string Message { get; private set; }        public int Priority { get; private set; }        public LoggerEventArgs(int p, string m)        {            Priority = p;            Message = m;        }    }    public class Logger    {        static Logger()        {            theOnly = new Logger();        }        private Logger()        {        }        private static Logger theOnly = null;        public static Logger Singleton        {            get { return theOnly; }        }        // Define the event:        public event EventHandler
               
                 Log;        // add a message, and log it.        public void AddMsg(int priority, string msg)        {            // This idiom discussed below.            EventHandler
                
                  l = Log;            if (l != null)                l(this, new LoggerEventArgs(priority, msg));        }    }
                
               

The AddMsg method shows an appropriate way to throw an exception. It is an important protection measure to reference the temporary variables of the log event handle in the static conditions of multi-threaded programs. C # The Compiler creates the add and remove accessors for the event:
Public event EventHandler Log
{
Add {log = log + value ;}
Remove {log = log-value ;}
}
Log usage:
    class ConsoleLogger    {        static ConsoleLogger()        {            Logger.Singleton.Log += (sender, msg) =>            {                Console.Error.WriteLine("{0}:\t{1}",                msg.Priority.ToString(),                msg.Message);            };        }    }

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.