Document directory
- 1 string. isnullorempty () and string. isnullorwhitespace ()
- 2 string. Equals ()
- 3 using statement
- 4 static)
- 5. Object and set Initiators
- Summary
Five tips have been introduced in C #/NET code streamlining optimization tips (1). This article will introduce five more tips.
1 string. isnullorempty () and string. isnullorwhitespace ()
In net2.0, the string type has a static method isnullorempty. In net4.0, the string class adds a new static method isnullorwhitespace. The names of the two methods can also be used to determine whether isnullorempty is a null reference and a Null String, while isnullorwhitespace is used to determine whether the blank reference and each character in the string is a space.
Before using these two methods, we need the following code to make such a judgment:
public string GetFileName(string fullPathFileName){ if (fullPathFileName == null || fullPathFileName.Length == 0) { throw new ArgumentNullException(fullPathFileName); } //...}
Use isnullorempty
public string GetFileName(string fullPathFileName){ if (string.IsNullOrEmpty(fullPathFileName)) { throw new ArgumentNullException(fullPathFileName); } //...}
The following is a new requirement. We need to connect the three names together, and want the intermediate name not to be a null string and no extra spaces. We will write the following code:
public string GetFullName(string firstName, string middleName, string lastName){ if (middleName == null || middleName.Trim().Length == 0) { return string.Format("{0} {1}", firstName, lastName); } return string.Format("{0} {1} {2}", firstName, middleName, lastName);}
The above Code uses trim to remove spaces and determine whether the length is 0. The Code is also very clear and concise, but it will generate additional string objects that affect performance, in this case, use the isnullorwhitespace method in net4.0.
public string GetFullName(string firstName, string middleName, string lastName){ if (string.IsNullOrWhiteSpace(middleName)) { return string.Format("{0} {1}", firstName, lastName); } return string.Format("{0} {1} {2}", firstName, middleName, lastName);}
The code above is very concise, and there is no need to worry about generating additional string objects without timely garbage collection, which affects performance.
2 string. Equals ()
The string. Equals method has many reloads for our use, but some of them are often ignored. We usually use the following method to compare strings.
public Order CreateOrder(string orderType, string product, int quantity, double price){ if (orderType.Equals("equity")) { } // ...}
If ordertype is nullNullreferenceexceptionTherefore, in order not to throw an exception, null must be judged before judgment, as shown below:
if (orderType != null && orderType.Equals("equity"))
It is equivalent to making two judgments each time, which is very troublesome and sometimes may be forgotten. If you use string. Equals, you can solve this problem. The Code is as follows:
if (string.Equals(orderType, "equity"))
When ordertype is null, the above Code does not throw an exception but directly returns false.
It is sometimes case sensitive when the string is determined to be equal. Many people prefer to convert the string to uppercase or lowercase for comparison (it is recommended to convert it to uppercase or lowercase for comparison, because the compiler has been optimized to improve performance), but when it is converted to uppercase or lowercase, it creates a string, reducing performance. In this case, use stringcomparison. invariantcultureignorecase. The Code is as follows:
if (orderType.Equals("equity", StringComparison.InvariantCultureIgnoreCase))
If you want to consider null, you should still use string. Equal
if (string.Equals(orderType, "equity", StringComparison.InvariantCultureIgnoreCase))
3 using statement
We all know that the most common use of using is to reference namespaces in classes. In addition, it can be used to set aliases and applications.IdisposableOn the object instance, you can make these objects automatically release resources within the scope of using. The following sample code does not use using:
public IEnumerable<Order> GetOrders(){ var orders = new List<Order>(); var con = new SqlConnection("some connection string"); var cmd = new SqlCommand("select * from orders", con); var rs = cmd.ExecuteReader(); while (rs.Read()) { // ... } rs.Dispose(); cmd.Dispose(); con.Dispose(); return orders;}
The code above is not very nice-looking and does not handle exceptions. If an exception occurs during code execution, some resources cannot be released in time, even though they will eventually be recycled, but it will still affect the performance. The following code adds Exception Handling
public IEnumerable<Order> GetOrders(){ SqlConnection con = null; SqlCommand cmd = null; SqlDataReader rs = null; var orders = new List<Order>(); try { con = new SqlConnection("some connection string"); cmd = new SqlCommand("select * from orders", con); rs = cmd.ExecuteReader(); while (rs.Read()) { // ... } } finally { rs.Dispose(); cmd.Dispose(); con.Dispose(); } return orders;}
The above code is still insufficient. IfSqlcommandIf the object fails to be created or an exception is thrown, RS is null. dispose () will throw an exception and cause con. dispose cannot be called, so we should avoid this situation.
public IEnumerable<Order> GetOrders(){ var orders = new List<Order>(); using (var con = new SqlConnection("some connection string")) { using (var cmd = new SqlCommand("select * from orders", con)) { using (var rs = cmd.ExecuteReader()) { while (rs.Read()) { // ... } } } } return orders;}
The using in the above Code is nested with several layers, which looks complicated and not very readable. We can improve it like below
public IEnumerable<Order> GetOrders(){ var orders = new List<Order>(); using (var con = new SqlConnection("some connection string")) using (var cmd = new SqlCommand("select * from orders", con)) using (var rs = cmd.ExecuteReader()) { while (rs.Read()) { // ... } } return orders;}
4 static)
Many people do not use static modifiers when creating classes. They may not know the role of static modifiers, some limitations imposed by the static modifier can make our code more secure when other developers use our code. For example, we now write an xmlutility class, which is used to implement XML serialization. The Code is as follows:
public class XmlUtility{ public string ToXml(object input) { var xs = new XmlSerializer(input.GetType()); using (var memoryStream = new MemoryStream()) using (var xmlTextWriter = new XmlTextWriter(memoryStream, new UTF8Encoding())) { xs.Serialize(xmlTextWriter, input); return Encoding.UTF8.GetString(memoryStream.ToArray()); } }}
The above is a typical XML serialization code, but we need to instantiate the class object before using the object to call the method.
var xmlUtil = new XmlUtility();string result = xmlUtil.ToXml(someObject);
This is obviously troublesome, but we can add a static modifier to the method, and then add a private constructor to the class to prevent class Instantiation to make the class easy to use.
public class XmlUtility{ private XmlUtility() { } public static string ToXml(object input) { var xs = new XmlSerializer(input.GetType()); using (var memoryStream = new MemoryStream()) using (var xmlTextWriter = new XmlTextWriter(memoryStream, new UTF8Encoding())) { xs.Serialize(xmlTextWriter, input); return Encoding.UTF8.GetString(memoryStream.ToArray()); } }}
The code above can implement classes to call methods directly, but it is not good to set private constructor for classes. When we mistakenly add non-static methods to classes, classes cannot be instantiated, the added non-static method is virtually empty.
public T FromXml<T>(string xml) { ... }
So we need to set the class to static. In this way, an exception will be thrown during compilation when there are non-static methods in the class, telling us that the class can only contain static members.
public static class XmlUtility{ public static string ToXml(object input) { var xs = new XmlSerializer(input.GetType()); using (var memoryStream = new MemoryStream()) using (var xmlTextWriter = new XmlTextWriter(memoryStream, new UTF8Encoding())) { xs.Serialize(xmlTextWriter, input); return Encoding.UTF8.GetString(memoryStream.ToArray()); } }}
To add a static modifier to a class, the class can only contain static members and cannot be instantiated. We cannot add a non-static member at will. Otherwise, the class cannot be compiled.
5. Object and set Initiators
In C #3.0 and later versions, new features of the object and set initiator are added, which makes the Code look more concise and may bring higher performance. The initialization tool is actually a syntactic sugar. The following example shows a structure.
public struct Point{ public int X { get; set; } public int Y { get; set; }}
Common Initialization is as follows:
var startingPoint = new Point();startingPoint.X = 5;startingPoint.Y = 13;
Use the initialization tool to initialize
var startingPoint = new Point() { X = 5, Y = 13 };
The code is indeed quite streamlined. Dropping from three lines to one line can reduce the number of words.
Next let's take a look at the initialization of the set. Suppose we add five Integers to a set list.
var list = new List<int>();list.Add(1);list.Add(7);list.Add(13);list.Add(42);
Use the set initializer. The Code is as follows:
var list = new List<int> { 1, 7, 13, 42 };
If you know the quantity to be loaded in advance, you can set the default capacity value for the list, as shown below:
var list = new List<int>(4) { 1, 7, 13, 42 };
The following is an example of how objects and collections are normally used together.
var list = new List<Point>();var point = new Point();point.X = 5;point.Y = 13;list.Add(point);point = new Point();point.X = 42;point.Y = 111;list.Add(point);point = new Point();point.X = 7;point.Y = 9;list.Add(point);
The following code uses the initialization tool. The differences are as follows:
var list = new List<Point>{ new Point { X = 5, Y = 13 }, new Point { X = 42, Y = 111 }, new Point { X = 7, Y = 9 }};
Using an object or set initializer brings us very simple code. Although a statement sometimes occupies multiple lines, it is quite readable.
In some cases, the performance will also be improved. See the following two classes.
public class BeforeFieldInit{ public static List<int> ThisList = new List<int>() { 1, 2, 3, 4, 5 };}public class NotBeforeFieldInit{ public static List<int> ThisList; static NotBeforeFieldInit() { ThisList = new List<int>(); ThisList.Add(1); ThisList.Add(2); ThisList.Add(3); ThisList.Add(4); ThisList.Add(5); }}
Both classes do the same thing. They both create a static list field and add one to five integers. The difference is that the first class will be added to the class in the generated il code.BeforefieldinitMark and compare the Il code generated by the two classes
.class public auto ansi beforefieldinit BeforeFieldInit extends [mscorlib]System.Object{} // end of class BeforeFieldInit .class public auto ansi NotBeforeFieldInit extends [mscorlib]System.Object{} // end of class NotBeforeFieldInit
For performance issues about static constructor, refer to CLR via C # learning notes (5) Performance of static Constructor
Summary
This article is based on the second article of the foreigner series blog. It is not a literal translation. For the original article, see the following link. I hope this article will help you.
Link: http://geekswithblogs.net/BlackRabbitCoder/archive/2010/09/02/c.net-five-more-little-wonders-that-make-code-better-2.aspx
C #/NET code streamlining optimization skills (1)
C #/NET code streamlining optimization skills (2)
C #/NET code streamlining optimization skills (3)