Wednesday, August 07, 2024

10 Takeaways for GitHub Copilot

Having used AI tool GitHub Copilot for a year, I realized that learning GitHub Copilot is like learning any software. The more you use it, the better you will be. Overall, my experience with GitHub Copilot was very positive. GitHub Copilot helped me boost my productivity and happiness of the software development. 

Here are a few tips to become a better software developer boosted by GitHub Copilot or any Artificial Intelligence tools.

 Tips

  • Open the relevant files.
  • Provide specific comments.
  • Reference code using #file.
  • Generate model class from the database.
  • Generate multiple classes in one prompt.
  • Write the prompt incrementally.
  • Reuse previous prompts. Give specific instructions.
  • Don't start a new session. Previous prompts will be gone.
  • Don't expect AI gives you the same result every time.
  • Double check the result. GitHub Copilot could have bugs.
  • Generate the commit description with GitHub Copilot.
  • Generate the PR description with GitHub Copilot
  • Explain the commit with GitHub Copilot
  • Explain the PR with GitHub Copilot
  • Suggest the fix from GitHub Copilot
  • Fix the unit tests related to the recent changes using GitHub Copilot

 Verdict

GitHub Copilot is easy to use in Visual Studio. It’s a delight to see Copilot’s suggestions. The time saved for the developers justifies the cost. GitHub Copilot and Jetbrains Resharper are complementary to each other. GitHub Copilot is better than Jetbrains Resharper in code auto-generating. GitHub Copilot can’t replace Jetbrains Resharper in areas such as live templates, code refactoring, and code navigation.

  • Increase developer productivity 
  • Increase developer happiness
  • Accelerate software development
  • Remain in your flow in the beloved editor (VS or VSCode)


Sunday, August 04, 2024

C# From-The-End Index Operator ^ C# 13

Implicit index access

With C# 13, the implicit “From-The End” index operator ^ can now be used in object initializers. You can use ^ to specify a position in a collection that is relative to the end of the collection.

For example, consider the following class.

class InitializerDemo
{
    public int[] integers { get; set; } = new int[5];
}

You can now use the following piece of code in C# 13 to take advantage of the index operator.

var arr = new InitializerDemo
{
    integers =
    {
        [0] = 100,
        [^1] = 1000
    }
};

When you execute the above program, arr.Integers[0] will have the value 100 while arr.Integers[4] will have the value 1000. 

C# Partial Properties C# 13

Partial properties

Partial properties, like partial methods, are a new feature added in C# 13. They support source generators and are used to separate the declaration of a property from its implementation code. Note that partial methods were introduced earlier and gained some traction in C# 9.

The following code snippet illustrates how partial properties can be used:

partial class MyClass
{
    string myField;
    public partial string MyProperty { get; set; }
    public partial string MyProperty
    { get => myField; set => myField = value; }
}

It should be noted that when you declare a partial property with accessors having semicolon bodies without any implementation code inside, it is assumed to be a defining declaration. By contrast, when a partial property has accessors that contain implementation code, it is considered to be an implementing declaration.

Partial properties are used to provide support for source generators. Their sole purpose is to isolate the declaration of a property from its implementation code.

C# Using ref and unsafe in async methods and iterators C# 13

 Using ref and unsafe in async methods and iterators

Before C# 13, declaring local ref variables or local variables of a ref struct type in either async methods or methods that use yield return, commonly known as iterator methods, was not possible. Nor could these methods have an unsafe context. C# 13 allows the declaration of ref local variables and local variables of a ref struct type in asynchronous methods. Similarly, C# 13 allows unsafe contexts in iterator methods.

You can also safely use types like System.ReadOnlySpan<T> in asynchronous and iterator methods. 

The primary benefit of using a ref struct is to get the benefit of pointers in a safe context and prevent memory allocation in several common scenarios. Hence, by using ref struct types in async methods and iterators, you can improve the performance of your application. This is the most useful new feature in C# 13 in my opinion.

C# 13 allows you to make a type argument a ref struct by specifying allows ref struct in the where clause of the type parameter. Note that if you use a type parameter specified with allows ref struct, then you are including all of the behaviors and restrictions of the ref struct type.

Consider the following piece of code that shows a ref struct and a method that uses it as a parameter.

ref struct TestStruct
{

}

TestStruct TestMethod<TestStruct>(TestStruct p)
    where TestStruct : allows ref struct
    => p;

The following code snippet illustrates how ref struct instances can be created and used inside an async method.

async Task<int> Test()
{
    TestStruct testStruct = new TestStruct();
    TestMethod(testStruct);
    return await Task.FromResult(0);
}

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
        }
    }

} 

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...