preface

Today the hero, but you and fuck the ear. — Cao Cao “Romance of The Three Kingdoms”

For programmers who have been working in IT for years, if you ask the most mainstream backend programming language in the country, I believe most of them will say Java. This is not surprising, given that Java has been around for more than 30 years, has a huge user base and ecosystem, and seems to dominate software engineering. However, as the ancients said, “He who wins the hearts of the people wins the world.” The programming language with the most users is not necessarily the most popular among developers. According to StackOverflow’s 2021 programming language satisfaction survey of 82,914 developers, Java ranked out of the top 20 with 47% faving it, just ahead of PHP, C, and COBOL. On the other hand, C#, known as the “clone of Java,” received 62% of developers’ satisfaction, 15% higher than Java. Although C# lags far behind Rust and TypeScript in terms of satisfaction, C# is gaining ground as an alternative to Java in terms of development efficiency, ease of deployment, and documentation perfection. Due to my work, I have used C# and Java to develop many projects, so I have a certain understanding of the similarities, differences, advantages and disadvantages between them. In my opinion, C# is more popular with developers than Java for some reason, because it is a better development experience.

Due to the limitation of space, the whole principle and practical introduction of C# (i.e. why it is recommended to build large backend applications in C#) will be split into a series of articles, which will analyze the “young” programming language in depth from the aspects of syntax features, development mode, ecosystem, deployment and construction. And take.net Core as an example to introduce how to build a large backend application with C#.

This article, the first in a series of articles on C#, focuses on some of the modern syntax features of C# in terms of syntax features and how they improve development efficiency.

C # profile

C# is a new programming language released by Microsoft in 2000. It has been labeled “copycat Java” since its inception because of its high similarity to Java. C# is an object oriented programming (OOP) language similar to Java. It contains OOP elements such as classes, methods, interfaces, and single inheritance. It is the foundation language for the Windows.net network framework. C# was released in connection with a lawsuit SUN filed against Microsoft to replace Visual J++, the Java variant that caused the dispute.

Since the release of version 1.0, C# has gone through many iterations, both large and small, with the release of version 9.0 with.net 5. From the earliest object-oriented support to richer features such as asynchronous programming and cross-platform support. As C# becomes more powerful, it also follows the “simple, modern, universal” design standard, and is well suited to the increasingly complex back-end development and architectural requirements of today. It can be used for both Windows desktop applications and more scalable distributed systems and microservices architectures.

C# syntax features

Probably a lot of C# features are similar to Java, such as the type system, object-oriented programming, dependency injection, exception handling, etc. This section introduces more features that are different from Java and that have greatly improved the development experience of C# and made it more appealing to developers.

A null value operation

In developing projects using C#, I have found that null values are much easier to determine and manipulate than they are in Java. Here are a few examples to illustrate the syntactic superiority of C#.

Example 1

If you want to fetch deeper elements from JSON objects, you generally need to do null values, which inevitably results in a lot of things like if (value == null) {… } such a judgment statement, appear unusually wordy. In C#, the null judgment is reduced to a question mark? . For example, you could write code to fetch deep JSON elements like this.

// access index C in member B of A A? .B? [C];Copy the code

In this way, you avoid a lot of if statements that automatically return the entire expression that fetched the value to NULL if one of the members is not present, which greatly simplifies the redundant code that comes with null values.

Example 2

Quite often, you may want to set a default value for an expression and return the default value if the expression is null. Take the following example.

// set default value of text if input is null
var text = input ?? '-';
Copy the code

Use the two-question mark operator?? , you will be able to easily set default values in C#. Otherwise, as in Example 1, you may have to add unnecessary if (value == null) statements. ?? Such operators are also code savers in C#.

C# has a number of other syntax for null-value operations, such as the null containment operator and nullable types, but the two examples above are the most common examples of null-value operators in C# and are useful for everyday C# project development.

If you’re familiar with another technical post on TypeScript, “Why TypeScript is a Necessary Language for Developing Large front-end Projects,” you’ll remember that TypeScript also has a null-value manipulation syntax. Yes, TS borrows from C# because the creator of TypeScript was Anders Hejlsberg, the father of C#!

Implicitly type a local variable

The reason why many Java developers complain that writing Java is like writing a long, stinking essay is because every time you declare a new variable in Java you have to think about its type, which takes a lot of brain power to deduce and memorize the type of the temporary variable. This is really not a good thing for development efficiency.

Taking cues from other programming languages that do not mandate variable type declarations, C# has integrated the Implicitly typed local variables syntax. I think implicitly typed local variables are a cool feature in C# that frees developers from having to force themselves to remember variable types that need to be referenced or declared and allows them to focus on code logic.

C# uses the var keyword in JavaScript to declare implicitly typed local variables, which allow the variable to be “automatically” declared by implicit type inference. An official example of the C# documentation is attached below to show how implicitly typed local variables can be used.

// i is compiled as an int
var i = 5;
​
// s is compiled as a string
var s = "Hello";
​
// a is compiled as int[]
var a = new[] { 0.1.2 };
​
// expr is compiled as IEnumerable<Customer>
// or perhaps IQueryable<Customer>
var expr =
    from c in customers
    where c.City == "London"
    select c;
​
// anon is compiled as an anonymous type
var anon = new { Name = "Terry", Age = 34 };
​
// list is compiled as List<int>
var list = new List<int> ();Copy the code

Of course, heavy use of VAR can also cause problems. For example, code that contains a large number of implicitly typed local variables can cause C# developers unfamiliar with the code to spend a lot of time trying to figure out the actual type of the variable, affecting the readability of the code. However, common C# ides such as Visual Studio or JetBrains Rider can automatically show you the actual type of the implicit type local variable. Thanks to these powerful ides, I recommend using C#’s var syntax to declare variables.

Language Integrated Query (LINQ)

In addition to the above two syntax for improving development efficiency, C# also has a very novel syntax feature: language integrated query, or LINQ for short. The advent of LINQ makes expressions for data source operations simple enough. I have reason to believe that the creators of C# must have referenced query languages like SQL to design LINQ syntax. Here is an example using LINQ.

class LINQQueryExpressions
{
    static void Main()
    {
​
        // Specify the data source.
        int[] scores = new int[] { 97.92.81.60 };
​
        // Define the query expression.
        IEnumerable<int> scoreQuery =
            from score in scores
            where score > 80
            select score;
​
        // Execute the query.
        foreach (int i in scoreQuery)
        {
            Console.Write(i + ""); }}}// Output: 97 92 81
Copy the code

Let’s focus on the scoreQuery variable expression, where the from… in … where … select … Syntax is LINQ. The idea is to iterate through scores, select only those elements whose score is greater than 80, and return scoreQuery, the new iterator of score stroke. This is similar to SQL SELECT… The FROM syntax is very similar. LINQ is just an expression for C# to make regular data manipulation, especially arrays, as easy as writing SQL. If you don’t use LINQ, you might need to run foreach through the array and do if judgments, then add more operations to implement the same logic as the LINQ statement above.

We’ll continue to cover data manipulation in C# later in the section that introduces the Entity Framework database manipulation Framework.

The attribute grammar

C# defines models in a much simpler way than Java, while supporting more advanced features such as computed properties defined by get or =>.

public class Person
{
  // private properties
  private int _gender;
  private int _age;
  
  // Auto-implemented property
  public string Name { get; set; }
  
  // Expression body definition
  public string Gender => _gender == 1 ? "Male" : "Female";
  
  // Property with backing fields
  public string Age
  {
    get
    {
      return $"{_age} years old"; }}}Copy the code

In the above example, we saw that there are several ways to define attributes. The Name attribute is automatically implemented. You only need to add get and set to indicate that the attribute is read and write. Gender is a simplified GET accessor denoting => for simpler computed attributes; Age contains get accessors for more complex computed properties.

As you can see, C#’s attribute syntax encompasses both simple and complex usage scenarios, thus making development more efficient.

conclusion

This article introduces the unique and convenient features of C# from the perspective of syntactic features. In particular, compared to the traditional backend programming language Java, C# has many favorite syntax, such as null-value operations, implicit type inference, LINQ, and so on. Although Java has added some similar syntax in the new version in an attempt to improve development efficiency, most of the Java products on the market today use the classic Java 8 version, so they do not have these features. C# is backed by Microsoft, has a sensible Roadmap and is well documented, so is very friendly for many back-end developers. C#’s current development direction implements its “simple, modern, universal” design standards, which are generally suitable for medium and large projects. However, due to historical reasons, Java is still the main market in China for the time being, while the emerging Go also occupies the share of distributed application field (refer to the previous article of this blog “Is the popular Golang really a panacea for back-end development? ), so C# may have some way to go. But good wine needs no bush. More and more developers, including this one, have realized that C# is an excellent back-end programming language that can be used in real-world projects if possible. The next series of articles will take a closer look at the C# ecosystem, particularly mainstream frameworks such as.net Core and Entity Framework.