C# - Basic

Created:2018-09-28  Last modified:2019-06-19


local variables must be assigned a value before using. members does not need to have.


  1. Types

    C# has two kinds of types: value types and reference types. But all types, including int, inherit from object.

    1. Value types

      Value types: primitive types, enum, struct, and nullable.

      1). sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal (128bit high-percision decimal), bool. (Java only has signed numbers)
      2). struct: Java does not have struct, this struct is similar to C/C++ struct
      3). Each type except null, e.g. int, string, has a nullable type e.g. int?, string?. The nullable type's value can be a normal value or null.

    2. Reference types

      reference types: Class, Interface, Array, and Delegate.

      Delegate (function pointer): delegate type represents references to methods with a particular parameter list and return type.

      Primitive types, null and array are provided by C#, developers can use them but not define them.
      Enum, struct, class interface and delegate are definable.
      class, struct, interface, delegate support generics.

    3. Box/Unbox

                      int i = 123;
                      object o = i;    // Boxing: allocate a space from heap, copy the value type's value into the reference type's space.
                      int j = (int)o;  // Unboxing: check if the box has the related value type; then copy the data out of the box into the value variable (on stack)
                  
    4. var

      var is used to define a variable only within a method scope. var defined variable has implicit type that provides by compiler. And this implicit type can already be defined e.g. string, it can also be some types that are not defined yet.

      Support: C# 3.0 and later

                      static void Main(string[] args)
                      {
                          var message = "Hello World!";
                          Console.WriteLine(message);
                          Console.WriteLine(message.GetType()); // System.String
      
                          var person =  new {  // var receive an anonymous class.
                              name = "Nan Qin", 
                              desc = "A nice person." };
                          Console.WriteLine(person.GetType()); // <>f__AnonymousType0`2[System.String,System.String]
      
                          // .name and .desc properties are read-only
                      }
                  
    5. Nullable Type

      C# value type's variables cannot be set to null. e.g. int, enum, struct ... If we declare a variable of value type without initializing a value, it will be set to its default value. However, C# provides a way to make these non-nullable value type variable nullable.

                      // int year = null;
                      // Cannot convert null to 'int' because it is a non-nullable value type.
      
                      int? year = null;    
                  

      With a question mark, now it become nullable, which means it can be set to null. Reference type is naturally "nullable", so the question mark cannot be used with reference type. However, reference type cannot be called nullable type, nuallable type are defined as value type with null.

      The ? is acutally implemented as a System.Nullable<T> generic.

                      System.Nullable<int> year = 10; // int + null => int?
      
                      int year = 2019;
                      int? year2 = null;
                      // year = year2 ; nullable type can be assigned to a non-nullable type.
                      bool same = (year == year2); // comparison is allowed.
      
                  

      Null conditional operator ?. (Elvis operator)

      ?. can form a chain, if any value is null, the evaluation of the expression is ended and return null.?. primarily used with reference type, nullable type does not need to have ?.

                      // nullable type does not need to have ?.
                      
                      int? year = null;
                      string month = null;
                      string str = year?.ToString();
                      str = year.ToString();
                      str = month?.ToString(); 
                      str = month.ToString(); // error.
      
                  

      Null-coalescing operator ??

      variable = expression/variable ?? expression/variable/value. If the lefthand-side is null, then return the righthand-side. So it does not make sense if the lefthand-side is a immediate value or a non-nullable type.

      The lefthand side of ?? can be nullable and reference type. Depending on the variable type, the righthand side may be OK to be nullable.

                      string text = "message";
                      int length = text?.Length ?? 0; // righthand side cannot be null since int cannot be null.
                      int? length2 = text?.Length ?? null; // righthand side be null since int? can be null.
      
                      
                  

      a ?? b ?? c === a ?? (b ?? c)

  2. Array

    1. Loop a multi-dimensional array
                                  int [,] arr= new int[2,2] {{1,2}, {3,4}};
                                  for (int i = 0; i < arr.GetLength(0); i++)
                                  {
                                      for (int j = 0; j < arr.GetLength(1); j++)
                                      {
                                          Console.WriteLine(arr[i,j]); // 1 2 3 4
                                      }
                                  }
                          
  3. Expression

    1. i++, i-- is allowed in C#, (Java, C, C++ as well), (Not allowed in Python)
    2. typeof(object): Obtains a Type object. Type is Class (Java Class class)
    3. (T)object: casting !!!!In C#, user can define how to cast variables. NEVER SEEN IN OTHER LANGUAGES.
    4. object as T: return a casted object. If cannot cast, return null.
    5. object is T: return true if object's type is T
    6. default operator
                              int i = default(int); // use default to obtain the default type 
                              string str = default(string);
                              Console.WriteLine(i); // 0
                              Console.WriteLine(str == null); // true
                          
    7. check/uncheck operator
      By default, variable value operation casued overflow is allowed. immediate value operation caused overflow is not allowed. is used to explicitly enable overflow checking for integral-type arithmetic operations and conversions
                              // Console.writeLine(2147483647 + 10); // immediate value addition overflow is not allowed, compile error.
                              Console.WriteLine(unchecked(2147483647 + 10)); // -2147483639, ignore this error.
                              int ten = 10;
                              Console.writeLine(2147483647 + ten); // -2147483639
                              Console.WriteLine(checked(2147483647 + ten)); // throw System.OverflowException 
                          
    8. C# string interploation
                          string name = "Tom";
                          int age = 2;
                          string sentence = $"{name} is {age} year{(age == 1 ? "" : "s")} old.";
                          Console.WriteLine(sentence); // Tom is 2 years old.
                      
  4. Flow control

    1. Switch (C# 7.0: any non-null expression), (C# 6.0: char, string, bool, integer, enum value)
      From JDK 7.0, java switch support String, and primitive types (cannot be null)
    2. Traditional if else if else, while, do-while, for
    3. foreach(string s in string_arr){} can be used if string_arr implemented System.Collections.IEnumerable
                              for(String s: string_arr){
      
                              } 
                              for(Iterator<String> it = string_collections.iterator(); it.hasNext();) {
                                  // java syntactic sugar for iterable collections
                              }
                              for(int i = 0; i < string_arr.length; i++){
                                  // for array.
                              } 
                          
    4. yield (python also has yield, and same function) is used to implement a iterator.
                              using System;
                              using System.Collections.Generic;
                              class X{
                                  public IEnumerable<int> action(){
                                      yield return 1;
                                      yield return 2;
                                      yield return 3;
                                  }
                              }
                              class Program
                              {
                                  static void Main(string[] args)
                                  {
                                      X temp = new X();
                                      foreach(int c in temp.action()){
                                          Console.WriteLine(c); // 1 2 3
                                      }
                                  }
                              }
                          
  5. Command Line

    1. dotnet

      dotnet is command line to for launching applications, initializing projects, installing dependencies
      dotnet cmd-name [cmd-options] [arguments]
    2. .csproj

      .csproj is the file defined project, dependecies and so on. It is like Node.js "package.json"
      <Project Sdk="Microsoft.NET.Sdk.Web">
          <PropertyGroup>
              <TargetFramework>netcoreapp2.2</TargetFramework>
              <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel><!--App configuration properties, see ASP.NET framework-->
              <RootNamespace>dotnet_web_api</RootNamespace>
          </PropertyGroup>
                                
          <ItemGroup>
              <PackageReference Include="Microsoft.AspNetCore.App" />
              <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
              <PackageReference Include="Npgsql" Version="4.0.5" />
          <ItemGroup>
                                
      </Project>
                                
                          

      .sln is Visual Studio IDE speicified file.

    3. dotnet new template-name [template-options] [new-options]

                          # dotnet create projects based on some well-defined template, such as console application template, asp.net template
                          dotnet new console --name test-project --output dir # create a project based on console template, which have name "test-project" and created in dir.
                      
    4. dotnet run [run-options] [program-inputs]

      run-options goes before program-inputs

                              # run-options:  --project project-location, default is current
                              #               --verbose show building message
                              #               --launch-profile, a profile is launchSetting.json used to configure ASP.NET apps. Console application does not have it by default.
                              #array                              by convention, console app is configured by appsettings.json
                              dotnet run
                          
    5. dependencies

      Microsoft using NuGet (same as the tool of Node.js npm) to manage packages. Go to https://www.nuget.org and find a right package, its webpage will also give a command to download this package.

                              dotnet add package Newtonsoft.Json --version 12.0.1
                          

      NuGet

      NuGet's default configuration file is in ~/.nuget/NuGet/NuGet.Config, which specify the where to find desired packages. e.g. Newtonsoft.Json. Once the package is found, it will be download into ~/.nuget/packages.

      When using "dotnet add package", it will create a entry
      <Include="Newtonsoft.Json" Version="12.0.1" />
      inside the .csproj, which indicates the project depends on Newtonsoft.Json version 12.0.1. Moreover, "dotnet add" will also automatically download this package to ~/.nuget/packages. And when running this app, the dotnet runtime will try to find the package under the ~/.nuget/package by default.

      dotnet restore

      dotnet restore will download the package that specified in .csproj