Sunday, August 04, 2024

C# New Lock Object C# 13

New Lock object

.NET 9 introduces a new thread synchronization type called System.Threading.Lock, which provides enhanced thread synchronization capabilities. Note that the runtime will detect whether the target of a lock is a Lock object, in which case it will use the updated API in lieu of the traditional API that uses System.Threading.Monitor. The compiler also will recognize if you convert a Lock object to some other type where System.Threading.Monitor code would be generated.

Let’s compare the old and new APIs. The code snippet below implements synchronization using the traditional API.

public class DbManager
{
    private object objLock = new object();
    public void InsertData()
    {
        lock (objLock)
        {
            //Your usual code to insert data to the database
        }
    }
}

To use the new API, you need to change only one line of code:

private System.Threading.Lock objLock = new System.Threading.Lock();

Hence, the updated DbManager class would have the following code.

public class DbManager
{
    private System.Threading.Lock objLock = new System.Threading.Lock();
    public void InsertData()
    {
        lock (objLock)
        {
            //Your usual code to insert data to the database
        }
    }

} 

Monday, July 29, 2024

C# Extension Types in C# 14

Since C# 3, extension methods have allowed you to add methods to an underlying type, even if you cannot change its code. LINQ is an example of a set of extension methods on IEnumerable<T>. The LINQ extension methods appear as if they were instance methods on the underlying type.

Proposed C# 14 takes the next step with extension types. This is a new kind of type that supplies extension members for an underlying type. They have methods, properties and other members that can be instance or static. Instance extension types cannot hold state. For example, they can’t include fields. They can access state on the underlying type or in another location.

There are two kinds of extension types: implicit and explicit extensions. Implicit extension types apply to all occurrences of the underlying type – in the same way extension methods do today. Explicit extension methods and properties apply only to instances of the underlying type that have been converted to the explicit extension type.

An extension type builds on an underlying type, which are just normal C# types. One of the reasons you might use an extension is that you can’t change the code of the underlying type.

Let’s look at some examples, starting with the underlying types and assuming we don’t have access to change their code:

public class Person()
{
    public required string GivenName { get; init; } 
    public required string SurName { get; init; }
    public required Organization Organization { get; init; } 
} 

public class Organization()
{
    public required string Name { get; init; }
    public required List<Team> Teams { get; init; }
} 

public class Team()
{
    public required string TeamName { get; init; }
    public required Person Lead { get; init; }
    public required IEnumerable<Person> Members { get; init; }
} 

A bit of LINQ code can return whether a Person is a lead. Since we don’t want to write this piece of code every time it’s needed, we could write an extension method, and if desired control access to it via namespaces. Or, we could use and implicit extension type to organize the extensions for the Person class, and provide IsLead as a property to all Person instances:

public implicit extension PersonExtension for Person
{
    public bool IsLead
        => this.Organization
            .Teams
            .Any(team => team.Lead == this);
}

This property would be called as:

if (person.IsLead) { ... }

Explicit extensions let you give extra features to specific instances of a type. For example, it makes sense to retrieve which teams a person leads. An explicit extension can provide the Teams property only to leads:

public explicit extension Lead for Person
{
    public IEnumerable<Team> Teams 
        => this.Organization
            .Teams
            .Where(team => team.Lead == this);
}

Both implicit and explicit extension types support static members as well as instance members. One way to use this is to provide defaults specific to your scenario. In this case, we have only one organization, and it’s quite awkward to specify it every time we create a person:

public implicit extension OrganizationExtension for Organization
{
   private static Organization ourOrganization = new Organization("C# Design");

   public static Person CreatePerson(string givenName, string surName) 
       => new(givenName, surName, ourOrganization);
}

Putting this together:

var mads = Organization.CreatePerson("Mads", "Torgersen");
// code to add more people and teams
if (mads.IsLead)
{
    Lead madsAsLead = mads;
    PrintReport(madsAsLead.Teams);
}

From a usage perspective, extension types allow you to simplify the code that provides the important work and logic of your application. It does this by organizing extensions and supplying extensions that customize specific instances of the underlying objects. From a technical perspective, extension types are an enhancement to the extension methods you use today. Learn more on Extension Types in Mads Torgersen and Dustin Campbell’s What’s new in C# talk


C# new params collections C# 13

 

C# 13

C# 13 focuses on flexibility and performance, making many of your favorite features even better. Enhancing params parameters are to provide you with more flexibility. 

Let’s take a look!

Enhancing C# params

params are no longer restricted to arrays! 

When the params keyword appears before a parameter, calls to the method can provide a comma delimited list of zero or more values and those values are placed in a collection of the parameter’s type. Starting in C# 13, the params parameter type can be any of the types used with collection expressions, like List<T>Span<T>, and IEnumerable<T>. What are the benefits of these overloads? By adding an IEnumerable<T> overload, support for LINQ is enabled. And by adding a ReadOnlySpan<T> or Span<T> overload, memory allocations can be reduced, enhancing performance. 

Just specify a different collection type as the parameter type:

void PrintList(params IEnumerable<string> list) 
    => Console.WriteLine(string.Join(", ", list));

PrintList("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");

// prints "Sun, Mon, Tue, Wed, Thu, Fri, Sat"

It’s really that easy to use the collection type that best fits your needs. Programmers using your method can just pass a comma delimited list of values. They do not need to care about the underlying type.

Making params better with spans

One important aspect of performance is reducing memory use, and System.Span<T> and System.ReadonlySpan<T>are tools in reducing memory allocations. You can learn more in Memory and Span usage guidelines.

If you want to use a span, just use the params parameter type to a span type. Values passed to the params parameter are implicitly converted to that span type. If you have two method signatures that differ only by one being a span and the other being an array and the calling code uses a list of values, the span overload is selected. This means you’re running the fastest code available and makes it easier to add span to your apps.

Many of the methods of the .NET Runtime are being updated to accept params Span<T>, so your applications will run faster, even if you don’t directly use spans. This is part of our ongoing effort to make C# faster and more reliable. It’s also an example of the attention we give to ensuring various C# features work well together. Here is an example from StringBuilder.

public StringBuilder AppendJoin(string? separator, params ReadOnlySpan<string?> values)

params and interfaces

The story gets even better with params support for interfaces. If no concrete type is specified, how does the compiler know what type to use?

Just like collection expressions in C# 12, when you specify an interface as a parameter type, it’s a clear indication that you just want anything that implements that interface. Key interfaces are mapped to implementation, so we can give you the best available type that fulfills the interface. The compiler may use an existing type or create one. You should not have any dependencies on the underlying concrete collection type because we will change it if a better type is available.

The great thing about this design is that you can just use interfaces for your params types. If you pass a value of a type that implements the interface, it will be used. When a list of values or a collection expression are passed, the compiler will give you the best concrete type.

Wednesday, November 02, 2022

10 Take-aways Moving MSSQL to PostgreSQL

Background: Based on my recent project, here are the 10 takeaways of MS SQL Server to PostgreSQL migration.
  1. Save the operating cost on SQL Server license. 
  2. PGSQL is case sensitive on char comparison. MSSQL is not case-sensitive. Therefore, the where clauses need to be reviewed in Entity Frameworks (EF). However, Entity Frameworks schema mapping is not case sensitive for C# property names on column names. 
  3. PGSQL supports uuid, which is the same as UniqueIdentifier in SQL Server.
  4. PGSQL timestamp without time zone can be used in MSSQL datetime.
  5. PGSQL 'RAISE NOTICE' equals to MSSQL 'PRINT'.
  6. PGSQL support the data type record. I found this very useful in the migration scripts.  (for loop)
  7. PGSQL block supports transaction. (do $$ ... $$) 
  8. PGSQL is very strict on semi-colon (;) for the statement ending.
  9. PGSQL doesn't support table variable.You need to used temp table instead. (temp table)
  10. DBeaver is very useful universal database management tool. 

Monday, April 04, 2022

Write Better Code. Be a better programmer!

Write better code — beautiful, explicit, simple, flat, sparse, readable, obvious, unambiguous,  and exception aware code — Be a better programmer.

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Monday, November 08, 2021

Good Parts of C# Language (v1 - v10)

Background: C# 10, along with .NET 6 and Visual Studio 2022, are released in November 2021. 

Here are the good parts in C#:
  1. C#  1: Anders Hejlsberg led the design of C#
  2. C#  2: Generics, nullable, anonymous methods
  3. C#  3: LINQ, extension methods, lambda expressions
  4. C#  4: dynamic, covariance and contravariance 
  5. C#  5: async/await, caller info
  6. C#  6: string interpolation, nameof, using static
  7. C#  7: span, ref struct
  8. C#  8: async streaming, patterns, indices and range
  9. C#  9: record, covariant return types, Lambda discard parameters
  10. C# 10: null parameter checking, lobal using, file namespaces

Tuesday, October 19, 2021

4 Take-aways for .NET Dictionary

Background: .NET has four built-in dictionary/map types.

Here are some take aways. 

  1. Hashtable - Avoid use hashtable because it is weakly typed.
  2. Dictionary<T> - Hashtable strongly typed replacement. Not thread safe
  3. ConcurrentDictionary<T> - Good read speed even in the face of concurrency, but it’s a heavyweight object to create and slower to update.
  4. ImmutableDictionary<T> - No locking required to read but more allocations require to update than a dictionary.

Be A Developer That Uses AI

Developers will not be replaced by AI, they'll be replaced by developers that use AI. Generative AI tools are revolutionizing the way de...