.NET Regular Expressions

Updated: 03 April 2024

Find all animals names starting with an uppercase C.

string pattern = @"\b[C]\w+";
Regex rg = new Regex(pattern);

string animals = "Cat, dog, Camel, caribou";
MatchCollection matchedAnimals = rg.Matches(animals);

for (int count = 0; count < matchedAnimals.Count; count++)
Console.WriteLine(matchedAnimals[count].Value);

C# date and time

Updated: 07 July 2023

Custom date and time format strings

string ds = "Sat 23 Dec 2023";
DateTime dt = DateTime.ParseExact(ds, "ddd dd MMM yyyy", CultureInfo.InvariantCulture);
Console.Write(dt.ToString());

Specify year, month, day, hour, min, seconds, UTC timezone

DateTime dt = new DateTime(2015, 12, 31, 5, 10, 20, DateTimeKind.Utc);

C# Regular Expressions

Updated: 07 July 2023

A brief example

string pattern = @"\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b";
Regex rg = new Regex(pattern);
string dates = "Tuesday 25th May & Monday 1st of Apr.";
MatchCollection matched_dates = rg.Matches(dates);

for (int count = 0; count < matched_dates.Count; count++)
Console.WriteLine(matched_dates[count].Value);

# May
# Apr

C# Properties and Fields

Updated: 30 January 2023

Properties enable a class to expose a public way of getting and setting values. Properties are special methods called accessors. A property is a member which can read, write or compute a private field.

The basic pattern involves a private backing field. Both get and set accessors may perform some conversion or computation on the data before it’s stored or returned.

public class TimePeriod
{
    private double _seconds;

    public double Hours
    {
        get { return _seconds / 3600; }
        set
        {
            if (value < 0 || value > 24)
                throw new ArgumentOutOfRangeException(nameof(value),
                      "The valid range is between 0 and 24.");

            _seconds = value * 3600;
        }
    }
}

Useage

TimePeriod t = new TimePeriod();
// The property assignment causes the 'set' accessor to be called.
t.Hours = 24;

// Retrieving the property causes the 'get' accessor to be called.
Console.WriteLine($"Time in hours: {t.Hours}");

More succinctly with expression bodies

public class SaleItem
{
    string _name;
    decimal _cost;

    public SaleItem(string name, decimal cost)
    {
        _name = name;
        _cost = cost;
    }

    public string Name
    {
        get => _name;
        set => _name = value;
    }

    public decimal Price
    {
        get => _cost;
        set => _cost = value;
    }
}

Auto-implemented properties

In some cases, property get and set accessors just assign/retrieve a value from a backing field without extra logic. By using auto-implemented properties, the C# compiler transparently provides the backing fields.

public class SaleItem
{
    public string Name
    { get; set; }

    public decimal Price
    { get; set; }
}

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties

C# generics

Updated: 28 January 2023

Generics are classes, structures, interfaces, and methods that have placeholders (type parameters) for one or more of the types that they store or use.

Generics introduces the concept of type parameters to .NET, which make it possible to design classes and methods that defer the specification of one or more types until the class or method is declared and instantiated by client code.

https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/types/generics

// Declare the generic class.
public class GenericList<T>
{
    public void Add(T input) { }
}

C# Anonymous types

Updated: 28 January 2023

Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first.

var v = new { Amount = 108, Message = "Hello" };

C# Lambda expressions and anonymous functions

Updated: 28 January 2023

A lambda expression is used to create an anonymous function. The lambda declaration operator => separates the lambda’s parameter list from its body.

Expression lambda. Returns the result of the expression

// (input-parameters) => expression

Statement lambda

// (input-parameters) => { <statement block> }

Action<string> greet = name =>
{
    string greeting = $"Hello {name}";
    Console.WriteLine(greeting);
};

// greet("World");

Input parameters

// none
Action line = () => Console.WriteLine();

// one
Func cube = x => x * x * x;
Func cube = (x) => x * x * x;

// two or more
Func testForEquality = (x, y) => x == y;

// with types
Func isTooLong = (int x, string s) => s.Length > x;

Discards specify input parameters which are not used in the expression

Func<int, int, int> constant = (_, _) => 42;

.NET dev environment inside docker

Updated: 09 August 2024

quick

Establish a development environment inside a running container

docker run -it \
--volume $(pwd):/source \
--workdir /source \
mcr.microsoft.com/dotnet/sdk:6.0

docker run -it \
--volume $(pwd):/source \
--workdir /source \
mcr.microsoft.com/dotnet/sdk:7.0

docker run -it \
--volume $(pwd):/source \
--workdir /source \
mcr.microsoft.com/dotnet/sdk:8.0

Create a hello world project

dotnet new console --framework net7.0 --use-program-main --name myapp

Run the app

cd myapp
dotnet run

publish & start an application dll

https://github.com/dotnet/dotnet-docker/blob/main/samples/dotnetapp/Dockerfile

Dockerfile

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /source

# copy csproj and restore as distinct layers
COPY *.csproj .
RUN dotnet restore

# copy and publish app and libraries
COPY . .
RUN dotnet publish -c Release -o /app --self-contained false --no-restore

# final stage/image
FROM mcr.microsoft.com/dotnet/runtime:6.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "source.dll"]

Build image based on Dockerfile above, in the same directory

docker build -t dndev .

Run a container

docker run dndev