Sunday, January 31, 2021

Azure/PowerShell: Listing All Locations

Certain Azure PowerShell cmdlets require a location parameter value be specified (e.g. East Asia, West US 2, Brazil South, etc.). In order to display list of of locations the following PowerShell script can be invoked:

Get-AzureRmLocation | Select-Object -Property Location, DisplayName

The location parameter of a cmdlet should be passed the DisplayName of a given resource location. The below example demonstrates this where a new resource group is created for Norway East:

New-AzResourceGroup `
    -Name 'rg_ahha_take_on_me' `
    -Location 'Norway East' | Out-Null

Invoking the above script on January 31, 2020 listed the following locations:


Saturday, January 30, 2021

Azure: Installing Azure CLI on OS/X

Microsoft documents installing the Azure CLI on OS/X at Install Azure CLI on macOS but unfortunately following these instructions results in an error. The aforementioned documentation shows the following introduction and brew command to be used to install the AzureCLI on OS/X 


The error generated by using the above brew command to install the Azure CLI on OS/X is as follows:

This command may take a few minutes to run due to the large size of the repository.
This restriction has been made on GitHub's request because updating shallow
clones is an extremely expensive operation due to the tree layout and traffic of
Homebrew/homebrew-core and Homebrew/homebrew-cask. We don't do this for you
automatically to avoid repeatedly performing an expensive unshallow operation in
CI systems (which should instead be fixed to not use shallow clones). Sorry for
the inconvenience!

The following command (removing the brew update &) install the Azure CLI on OS/X without error:

brew install azure-cli


Monday, January 25, 2021

C# 9.0: Record Types Non-Destructive Mutation (the With expression)

A C# 9.0 record type is immutable but there are times when it is useful to make a copy of a record type but only modify a subset of the properties. Under this scenario, the with express can be used with facilitates non-destructive mutation. To quote Steve Fenton's blog (C# 9 Non-Destructive Mutation): 


To demonstrate non-destructive mutation consider the following record type, a positional record (see C# 9.0: Positional Records):

public record Employee (
                  string Name, 
                  string Department,
                  string Office)
{
}    

The code below uses the with expression to make a copy of a record but allows specific properties to be changed in the newly created record and obviously does not modify the original record:


In the coding sample above, the first Employee record created is assigned to variable, victoria (line 13). The above code utilizes with expressions and behaves as follows:
  • Line 14: the victoria record instance is used to create a new employee, mario, but assigns a new value to the Name property, Mario Aguayo,
  • Line 15: the victoria record instance  is used to create a new employee, tarun, but assigns a new value to the Name property, Tarun Tiwari.
  • Line 16: the victoria record instance  is used to create a new employee, kai, but assigns a new value to the Name property, Kai Feng and Department property, QA.
  • Line 17: the kai record instance is used to create  a new employee, daisuke, but assigns a new value to the Name property, Daisuke Katchi and Office property, Via Carmen Suites.
 

Sunday, January 24, 2021

C# 9.0: Positional Records

This post introduces C# 9.0 positional records. Recall C# 9.0 record types were introduced in the post, C# 9.0: Record Types. A positional record is declared with a list of parameters such those shown below in lines 25 to line 29:


The record created contains an auto-property for each parameter in the declaration (PatientProperty, Count, Start, End, and DateRange). Each auto-property has a public access level. Auto-properties have a get and init access specifier (see: C# 9.0: Init Only Setters). The names of the parameters shown above were made uppercase so that the names of the auto-properties would be uppercase following the naming convention for properties.

Five parameters were specified in declaring the Patients record. The compiler creates a corresponding primary constructor taking the same five parameters as arguments. An example of the invocation of the primary constructor is as follows where the factory method, CreateDay, creates an instance of Patients where the parameters are passed at lines 43 through 47:


The auto-property, PatientProperty, is an enumeration also named PatientProperty. Use of the auto-property PatienProperty is shown below being used internally by the Patients class (lines 31, 33, and 35 below):


The PatientProperty property is never explicitly declared as all properties of the record corresponding to the declaration parameters are auto-properties and the compiler auto created each property. 

The PatientProperty enumeration is decorated by the Flags attribute (see FlagsAttribute Class) meaning that the enumerations values can be combined as they are bit fields. Lines 31, 33, and 35 above show the PatientProperty auto-property being used with the bitwise AND operator (&) in order to determine if the Patients in the date range are IsCovid19, IsIcu, or IsVentilator.

The source for this example is follows using screenshots from Visual Studio Code:

The source code in text form is found in Appendix A; Source Code at the end of this post.

Default Constructor

There is no default (parameterless) constructor created by the compiler for a positional record. It is illegal to create a parameterless constructor for a positional record. Below is an example (which will not compile) where the parameterless constructor is created and invoked at lines 47 to 53 using nominal object creation:


The error created while compiling the code above using Visual Studio Code is as  follows:

Appendix A: Source Code

The source code in its entirety is as shown below and of note:

  • There is no constructor explicitly declared for the class as the primary constructor is created by the compiler based on the parameters specified when the record was declared. 
  • The five parameters specified when the record was declared do not have explicit property declarations as the compiler automatically create this properties (auto-properties).
  • Other properties can be declared such as IsIcu, IsCovid19, and IsVentilator. The values for these parameters are computed using auto-properties assigned based on the parameters passed to the primary constructor. 
  • There is no implicit default constructor created for the record.

using System;

namespace HealthDashboard.Models 
{
    public enum DateRangeType 
    {
        Day,
        Week,
        Month,
        Quarter,
        Biannual,
        Year,
        Custom
    }

    [Flags]
    public enum PatientProperty
    {
        Covid19 = 0x1,
        Icu = 0x2,
        Ventilator = 0x4
    }

    public record Patients(
        PatientProperty PatientProperty,
        int Count,
        DateTime Start,
        DateTime End,
        DateRangeType DateRange) 
    {
        public bool IsCovid19 => 
           (0 != (PatientProperty & PatientProperty.Covid19));

        public bool IsIcu  => 
            (0 != (PatientProperty & PatientProperty.Icu));

        public bool IsVentilator => 
             (0 != (PatientProperty & PatientProperty.Ventilator));

        public static Patients CreateDay(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddDays(1), 
                    DateRangeType.Day);
        }                            

        public static Patients CreateWeek(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddDays(7), 
                    DateRangeType.Week);
        }                            

        public static Patients CreateMonth(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddMonths(1), 
                    DateRangeType.Month);
        }                           

        public static Patients CreateQuarter(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddMonths(3), 
                    DateRangeType.Quarter);
        }                            

        public static Patients CreateBiannual(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddMonths(6), 
                    DateRangeType.Biannual);
        }                            

        public static Patients CreateYear(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddYears(1), 
                    DateRangeType.Year);
        }                            

        public static Patients CreateCustom(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start,
                    DateTime end)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    end, 
                    DateRangeType.Custom);
       }    
    }
}







Saturday, January 23, 2021

C# 9.0: Record Types

C# 9.0 introduces a read-only object type created using the record keyword versus the keywords struct or class. This post introduces record instances created using positional object creation (recall C# Nominal versus Positional Object Create). A future post will introduce creating record instances defined using nominal syntax, demonstrate declaring record types with positional syntax, and show the use of the with keyword in conjunction with record types.

Up until C# 9.0 objects were defined using the class (reference type) or struct (value type) keywords. Such objects are typical mutable. It should also be recognized that anonymous types are reference types and tuples are value types, but objects are explicitly defined using the class and struct keywords. 

The record keyword, to no surprise, defines an object of type record where record instances are immutable, reference object types. It is possible to define immutable types using class and struct such as the System.String class. The elegance of the record keyword is that it is clear that an instance of a record is immutable and the compiler creates constructs that support immutability that are built into each record instance. The following sections of this post expand on these ideas:

  • Appendix A: Comparing Record Type Instances
  • Appendix B: Record Type Compiler Synthesized Methods

The C# record to be implemented will be used to track patient hospitalization for a heath dashboard. That is certainly information that is important to provide but should also be immutable. The properties exposed by the Patients record are as follows:

  • IsCovid19: true if patients are Covid-19 positive
  • IsIcu: true if patients are in the I.C.U.
  • IsVentilator: true if patients use ventilators.
  • Count; number of patients
  • Start: patient information start date
  • End: patient information end date
  • RangeType: type of patient information date range (day, week, month, quarter, biannual, year or custom)

The DataRangeType enumeration is used to specify the RangeType property of the Patients record:


The code for the Patients record is shown below. Some things to note with regards to the code:

  • There is no set for each property (lines 18 to 30) as the properties can only be assigned at initialization. The init keyword could also be explicitly specified (see C# 9.0: Init Only Setters).
  • Fit and Finish (discussed in C# 9.0: Fit and Finish) is used at lines 50, 60, 70, 90, 100, and 111.
  • All source code below is provide in text form in Appendix C: Source Code.



Assigning a value to a Property After Instantiation

The code snippet below results in a complication error as it is a compile time error to modify a field or property of a record after it is instantiated:


The compiler errors from Visual Studio Code caused by line 116 (above) are as follows:



Appendix A: Comparing Record Type Instances

Microsoft's documentation on record types, Create Record Types, provides an excellent explanation of how record type instances are compared:

Appendix B: Record Type Compiler Synthesized Methods

Microsoft's overview of C# 9.0 features contains a comprehensive overview of record types (see What's new in C# 9.0: Record Types). To quote Microsoft's documentation on records: 

Appendix C: Source Code

using System;

namespace HealthDashboard.Models 
{
    public enum DateRangeType 
    {
        Day,
        Week,
        Month,
        Quarter,
        Biannual,
        Year,
        Custom
    }

    public record Patients 
    {
        public bool IsCovid19 { get; }

        public bool IsIcu { get; }    

        public bool IsVentilator { get; }    

        public int Count { get; }

        public DateTime Start { get; }   

        public DateTime End { get; }   

        public DateRangeType RangeType { get; }

        public Patients(
                    int count, 
                    bool isCovid19, 
                    bool isIcu, 
                    bool isVentilator,
                    DateTime start,
                    DateTime end,
                    DateRangeType rangeType) => 
                        (Count, IsCovid19, IsIcu, IsVentilator, 
                                Start, End, RangeType) =
                            (count, isCovid19, isIcu, isVentilator, 
                                start.Date, end.Date, rangeType);

        public static Patients CreateDay(
                    int count, 
                    bool isCovid19, 
                    bool isIcu, 
                    bool isVentilator,
                    DateTime start)
        {
            return new(count, isCovid19, isIcu, isVentilator, start, 
                       start.AddDays(1), DateRangeType.Day);
        }                  
          
        public static Patients CreateWeek(
                    int count, 
                    bool isCovid19, 
                    bool isIcu, 
                    bool isVentilator,
                    DateTime start)
        {
            return new(count, isCovid19, isIcu, isVentilator, start, 
                       start.AddDays(7), DateRangeType.Week);
        }             
               
        public static Patients CreateMonth(
                    int count, 
                    bool isCovid19, 
                    bool isIcu, 
                    bool isVentilator,
                    DateTime start)
        {
            return new(count, isCovid19, isIcu, isVentilator, start, 
                       start.AddMonths(1), DateRangeType.Month);
        }              
             
        public static Patients CreateQuarter(
                    int count, 
                    bool isCovid19, 
                    bool isIcu, 
                    bool isVentilator,
                    DateTime start)
        {
            return new(count, isCovid19, isIcu, isVentilator, start, 
                       start.AddMonths(3), DateRangeType.Quarter);
        }              
              
        public static Patients CreateBiannual(
                    int count, 
                    bool isCovid19, 
                    bool isIcu, 
                    bool isVentilator,
                    DateTime start)
        {
            return new(count, isCovid19, isIcu, isVentilator, start, 
                       start.AddMonths(6), DateRangeType.Biannual);
        }              
              
        public static Patients CreateYear(
                    int count, 
                    bool isCovid19, 
                    bool isIcu, 
                    bool isVentilator,
                    DateTime start)
        {
            return new(count, isCovid19, isIcu, isVentilator, start, 
                       start.AddYears(1), DateRangeType.Year);
        }              
              
        public static Patients CreateCustom(
                    int count, 
                    bool isCovid19, 
                    bool isIcu, 
                    bool isVentilator,
                    DateTime start,
                    DateTime end)
        {
            return new(count, isCovid19, isIcu, isVentilator, start, 
                       end, DateRangeType.Custom);
        }                            
    }
}


Friday, January 22, 2021

Azure: Selecting a Virtual Machine Capable of Running Docker

In the post, Configuring VMWare Fusion to Support Docker Running on the Guest OS, it was pointed out that nested virtualization consumed a significant number of resources. Windows 10 running under VMWare Fusion on a MacBook Pro 2017 with an I7 and 16 GB of RAM was unusable when a Docker container was run on the Guest OS. One way to avoid purchasing a new computer is to create a virtual machine in Azure or AWS that is capable of Docker development. Microsoft provides a $150 per-month Azure credit with an MSDN subscription which makes an extremely powerful virtual machine cost nothing provided the VM is deallocated when not in use. 

Rather naively, a B Series Azure VM was created. The Docker Desktop crashed with an error when run on this virtual machine. The error stated that virtualization was not supported and the BIOS should be modified to support virtualization. As it turns out, not all VM series in Azure support nested virtualization. The innocuous blog post, Nested Virtualization in Azure, on Microsoft's Azure site identifies that nested virtualization is supported by Dv3 and Ev3 series virtual machines. Later versions than V3 of the D and E series virtual machines also support nested virtualization.

A VM was created using a Standard D-Series V4 (8 vcpus, 32 GiB memory) virtual machine at a cost of $373.03 per-month in West US. By deallocating the VM when not in use it can be run eight hours a day, seven days a week without exceeding the $150 per-month free credit. Docker ran without issue on the D-Series V4 (8 vcpus, 32 GiB memory) virtual machine.

Appendix A: Azure Virtual Machine Series

Azure's documentation on virtual machines, Virtual Machine series, presents a comprehensive overview of the virtual machine series (categories). Excerpts from this documentation are as follows:



























Wednesday, January 20, 2021

Configuring VMWare Fusion to Support Docker Running on the Guest OS

My personal Windows device is a Windows 10 guest OS that is hosted on a MacBook Pro running OS/X with VMWare Fusion. After installing Docker (Install Docker Desktop on Windows) I received numerous errors that the BIOS was not configured to support virtualization.

To enable virtualization the VM's Settings | Processors and Memory need to be modified. In VMWare Fusion the settings for a VM can be found by right clicking the virtual machine (the VM's name is W10Core3 which is now a .NET 5 VM) and selecting Settings from the context menu:


The Settings dialog (see below) contains Systems Settings group in which there is a Processors & Memory icon:


Clicking on the Processors & Memory icon displays the Processors & Memory dialog (see below). Expand Advanced options at the bottom of the dialog:


From the Advanced options section check the Enable hypervision applications in this virtual machine checkbox (see below):

Enable hypervision applications in this virtual machine is not a Windows 10 specific setting. The Guest OS running Docker would be Linux, Windows 10 or OS/X.

The MacBook Pro running VMWare Fusion with the Windows 10 guest OS is configured as follows:


When Docker is running, OS/X is running Windows 10 via VMWare Fusion and the Windows 10 is running WSL 2 which is Linux virtualization. This is nested virtualization and running Docker makes Windows 10 nearly unusable and subject to application crashes.

My solution to this was to create an Azure VM using my $150 per-month Azure credit received through my MSDN subscription but the details of this are a future post. 

Friday, January 15, 2021

C# Nominal versus Positional Object Creation

C# 9.0 introduces positional record types. Before discussing this language feature, a review is needed of the different styles of object creation in C#:

  • Positional: the properties of a class that require initialization are passed as parameters to a constructor. The constructor initializes the properties by assigning parameters to properties.
  • Nominal: the constructor for a class takes no parameters or fewer parameters than the number of properties that require initialization. When the object is constructed the properties are assigned using an object initializer.

To clarify the terms positional, nominal and object initializer consider the following class used to represent a technical certification: 

An example of positional object creation is as follows:


Line 30 shows positional object creation and line 33 shows positional object creation C# 9.0 fit and finish.

An example of nominal object creation is as follows where object initializes used to assign the Name and Description properties:


Line 30 shows nominal object creation and line 33 shows nominal object creation C# 9.0 fit and finish.





 

Visual Studio Code: Disabling Code References on Windows (a.k.a. Disabling CodeLens)

When including code snippets in documentation or a PowerPoint presentation it is desirable to remove N References displayed by default in a Visual Studio Code window. The code below shows 0 References to the class Certification (line 3), 1 reference to the Name property (line 15), and 1 reference to the Description property (line 17):


The reference information is provided by CodeLens and after disabling CodeLens, the code window appears as follows:


To disable CodeLens invoke the File Menu's Preferences menu item and select Settings (File | Preferences | Settings): 

From the User page, select the Text Editor tab and scroll until the Code Lens checkbox is visible: 


Uncheck the Code Lens checkbox.

An excellent write up on CodeLens can be found at Extensions using CodeLens.

C# 9.0: Fit and Finish

In some respects C# 3.0's var keyword is the foil to C# 9.0's fit and finish feature. Microsoft's overview of C# 9.0 features (What's new in C# 9.0) defines fit and finish as:

With the var keyword, the type of a variable is known based on the type assigned such as the following where the type is DateTime:

var lastTime = new DateTime(2020, 13, 31, 23, 59, 59);

C# 9.0's fit and finish removes the need for the type associated with the new keyword as the declaration makes this known:

DateTime valentinesDay = new(2021, 2, 14, 12, 0, 0);

Fit and finish can be used in field initialization (see line 11, 13, and 15):


Fit and finish can be used in conjunction with init only setters. To demonstrate consider the following class:


An instance of the Employee class can be instantiated as follows using fit and finish:

Employee employee = new() { Name = "Joe", Salary = 100000 };


Thursday, January 14, 2021

C# 9.0: Init Only Setters

 C# 9.0 introduces init only setters which allow properties to be assigned when an object is constructed and after construction those properties are read-only. To understand how init only setters are beneficial consider the Employee class:


The Salary property (line 9) has a private setter which means to initialize this property a value must be passed to the constructor (line 5). Imagine a case where the Employee class had thirty properties with private setters. The constructor in this case would contain an unmanageable number of parameters. 

An example of an init only setter is Employee class' Salary property (line 18):


The Salary can be set at initialization such as:

var employee = new Employee { Name = "Joe", Salary = 100000 };

The Name property is public and can be assigned after initialization. The Salary property uses an init only setter which means it cannot be assigned after initiation.