Visual Studio 2022 | DataTips penceresini sabitleme

Visual Studio 2022 17.1 Preview 2 ile birlikte, DataTips penceresini sabitleme özelliği geldi.

Şimdiye kadarki versiyonlarda datatips penceresi fareyi üzerinden çektiğiniz anda kayboluyordu ve çok derin bir listeye bakıyorsanız hepsini baştan açmanız gerekmekteydi. Doğal olarak çok sinir bozucu olabiliyor bu durum.

VS 2022 ile birlikte, bu pencereyi pencerenin dışında bir yere tıklamadığınız sürece sabitleyebileceğiniz bir özellik geldi. Bunun için Tools -- Options -- Debugging -- General kısmındaki “Keep expanded data tips open until clicked away” seçeneğini aktif edebilirsiniz.

Kaynaklar: https://docs.microsoft.com/en-us/visualstudio/releases/2022/release-notes#1712–visual-studio-2022-version-1712-newreleasebutton

JIT Derleyicisine Giriş – Loop Cloning ve Loop Hoisting

.NET içerisinde Common Language Runtime‘ın bir parçası olan JIT compiler‘ın Loop cloning ve Loop Hoisting (Loop-invariant code motion olarak ta geçiyor) konularında yaptıklarına değindik bu videoda.

Kaynaklar:

https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA+ABATARgLABQGAzAATakDCphA3oaY6QPTOkAyEEADlQDYQAdgEtBAc1IA3GBy68AEhGEBnAC6ixDJiXIpSAWRwAKUaoDaAXVIBDKFAA0pUzcfPgAShoEmpWj59a/qQAZtAmgqpOpAC8pAAMANxRADykOHGJTgDUWe6B/vTeQf62UGbCVrHWpFmkwAn5PgC++S1FjPmssjz8QhqkgHqAtqp8toCMgPmdbAAqwrzOEHwAttZ8E+0sbABC1srCkcDCUDZQqmOA+oCkiytrU6Sp16vrARtdAAowANbCKSdQAHTsGDiVQACwA/JMNp0AFQ6DB6fRYcLmKylVwRFxOTEeLw+QrFJzBIylQHAsRgmKxOKkNBoP5kkGg+5pDJxPIbfGNYpiCCqCCkZQCADuDU5TDahO5jEktlIoKUahiNhqdTFUvFjFCUCMsuOP2pSR+qXSGSNOQ5hIJhKYpXKlXlitU6uKkuK0vIAHYXUEPUKIMKQB7tbq5Qb4kaWabMsILR7rTa/vbldVavUPW7GE0YcxCE0gA===

https://en.wikipedia.org/wiki/Loop-invariant_code_motion

https://github.com/dotnet/coreclr/blob/master/src/jit/loopcloning.cpp

Leetcode Çözümleri | Binary Tree Inorder Traversal

Leetcode içerisinde bulunan “Binary Tree Inorder Traversal” sorusunun açıklaması ve çözümü. Bu soruda size verilen bir binary tree‘nin node’larını inorder traversal, yani öncelikle rekürsif olarak sol tarafı, sonra head nodu, sonra da rekürsif olarak sağ tarafı geri döndürmeniz isteniyor.

➡️ Tree traversal: https://en.wikipedia.org/wiki/Tree_traversal

➡️ Leetcode 94. Binary Tree Inorder Traversal: https://leetcode.com/problems/binary-tree-inorder-traversal/

➡️ Problem açıklaması:

Given the root of a binary tree, return the inorder traversal of its nodes’ values.

Example 1:

Input: root = [1,null,2,3]

Output: [1,3,2]

Example 2:

Input: root = []

Output: []

Example 3:

Input: root = [1]

Output: [1]

Constraints:

The number of nodes in the tree is in the range [0, 100].

-100 <= Node.val <= 100

Follow up: Recursive solution is trivial, could you do it iteratively?

JIT Derleyicisine Giriş – Tam sayı aritmetiği

.NET içerisinde Common Language Runtime‘ın bir parçası olan JIT compiler’ın tam sayı aritmetiği konusunda yaptıklarına değindim.

JIT derleme, interpreted programların performansını iyileştirmeye yönelik bir yöntem. Runtime sırasında, performansını artırmak için program assembly kod’ta derlenebilir. Buna sürece “dinamik derleme” de deniliyor.

Bu kavram ilk olarak John McCarthy’nin 1960 yılında yayınladığı ” Recursive functions of symbolic expressions and their computation by machine, Part I” çalışmasında belirtilmiş: http://jmc.stanford.edu/articles/recursive/recursive.pdf

Ayrıca şurada da “A Brief History of Just-In-Time” şeklinde güzel bir makale var: http://eecs.ucf.edu/~dcm/Teaching/COT4810-Spring2011/Literature/JustInTimeCompilation.pdf

JIT derlemenin statik derlemeye göre bazı avantajları vardır. C# uygulamalarını çalıştırırken, “runtime” uygulama çalıştırılırken uygulamanın profilini (profiling) çıkarabilir. Bu, daha optimize edilmiş kodun oluşturulmasına izin verir. Uygulama çalışırken davranışı değişirse, runtime bu kodu yeniden derleyebilir.

Dezavantajlardan bazıları, startup gecikmeleri ve runtime sırasında derleme ek yükünü barındırmak. Ek yükü sınırlamak için birçok jit derleyicisi yalnızca sık kullanılan kod kısımlarını derler mesela.

C# içerisinde bir kodun derlenme süreci şu şekilde;

1. Derleme, sırasında kaynak kodunuzu MSIL veya IL (tam özellikli bir dildir bu arada IL fakat C#’a göre biraz daha düşük seviyede) çevirir ve gerekli meta verileri oluşturur.

2. Runtime sırasında, JIT derleyicisi, aldığı IL kodunu assembly koduna çevirir. (Kullandığı runtime ve architecture’a göre üretilen assembly kodu da değişir. Örneğin; x86, x64 veya ARM gibi). Bu nedenle .NET Runtime assembly dosyalarınızın içerisindeki IL kodunu yorumlamaz.

3. CLR, kodun çalıştırılmasını sağlayan altyapıyı ve runtime sırasında kullanılabilecek hizmetleri sağlar. Derlenmiş makine kodu, kod bölümünün bir sonraki çalıştırılışında yeniden kullanılabilecek şekilde bellekte tutulur. Bir işlevi ikinci kez çağırdığınızda, onu ilk çağırdığınızdan daha hızlı çalışacaktır çünkü ikinci kez herhangi bir JIT adımı gerekli değildir.

Bunların hepsine genel olarak “managed execution” adı verilir.

Bu arada assembly kodları içerisinde sıklıkla görebileceğiniz bazı temel cpu register’ları şu şekilde;

EAX — Değerleri toplamak için kullanılan özel bir register

ECX — Counter (döngülerde ve string’lerde kullanılır)

EDX — EAX ile birlikte kullanılan, kısa süreli değişkenleri tutan register

EBX — Data depolamak için genel bir register. Dizilerde kullanılır.

Son olarak, JIT compiler açık kaynaktır. Şu Github sayfasından inceleme yapabilirsiniz:

https://github.com/dotnet/coreclr/tree/master/src/jit

Kaynaklar:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/bitwise-and-shift-operators#right-shift-operator-

https://en.wikipedia.org/wiki/Logical_shift

https://en.wikipedia.org/wiki/Arithmetic_shift

https://en.wikipedia.org/wiki/X86_instruction_listings

https://en.wikipedia.org/wiki/Just-in-time_compilation

Leetcode Çözümleri | 3SUM

Leetcode içerisinde bulunan “3Sum” sorusunun açıklaması ve çözümü. Bu soruda size verilen bir tam sayı dizisinde, toplamları 0 olan üçlü sayı kümelerini tekil (distinct) olarak bulmanız isteniyor.

➡️ Videoda bahsettiğim “Two Sum” problemi: https://youtu.be/cHDvgJK79sI

➡️ LeetCode 15. 3Sum: https://leetcode.com/problems/3sum/

➡️ Problem açıklaması:

Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.

Notice that the solution set must not contain duplicate triplets.

Example 1:

Input: nums = [-1,0,1,2,-1,-4]

Output: [[-1,-1,2],[-1,0,1]]

Example 2:

Input: nums = []

Output: []

Example 3:

Input: nums = [0]

Output: []

Constraints:

0 <= nums.length <= 3000

-10^5 <= nums[i] <= 10^5

Leetcode Çözümleri – Evaluate Reverse Polish Notation

Leetcode içerisinde bulunan “Evaluate Reverse Polish Notation” sorusunun açıklaması ve çözümü. Bu soruda size verilen bir “reverse polish notation”‘ın sonucunu geriye döndürmeniz isteniyor.

➡️ Reverse Polish Notation nedir? https://en.wikipedia.org/wiki/Reverse_Polish_notation

➡️ LeetCode 150. Evaluate Reverse Polish Notation: https://leetcode.com/problems/evaluate-reverse-polish-notation/

➡️ Problem açıklaması:

Evaluate the value of an arithmetic expression in Reverse Polish Notation.

Valid operators are +, -, *, and /. Each operand may be an integer or another expression.

Note that division between two integers should truncate toward zero.

It is guaranteed that the given RPN expression is always valid. That means the expression would always evaluate to a result, and there will not be any division by zero operation.

Example 1:

Input: tokens = [“2″,”1″,”+”,”3″,”*”]

Output: 9

Explanation: ((2 + 1) * 3) = 9

Example 2:

Input: tokens = [“4″,”13″,”5″,”/”,”+”]

Output: 6

Explanation: (4 + (13 / 5)) = 6

Example 3:

Input: tokens = [“10″,”6″,”9″,”3″,”+”,”-11″,”*”,”/”,”*”,”17″,”+”,”5″,”+”]

Output: 22

Explanation: ((10 * (6 / ((9 + 3) * -11))) + 17) + 5

= ((10 * (6 / (12 * -11))) + 17) + 5

= ((10 * (6 / -132)) + 17) + 5

= ((10 * 0) + 17) + 5

= (0 + 17) + 5

= 17 + 5

= 22

Constraints:

1 <= tokens.length <= 10^4

tokens[i] is either an operator: “+”, “-“, “*”, or “/”, or an integer in the range [-200, 200].

Switch içerisinde Hash Table optimizasyonu [C#]

C# compiler’ının switch statement’ı içerisinde 7. case’den sonra bir hash table optimizasyonu yaptığını biliyor muydunuz?

C# compiler’ı switch statement‘ını 6 tane case sayısına ulaşana kadar lowering mekanizması ile standart if else ifadelerine çeviriyor.

Fakat case sayısı 7’ye ulaştığında lowering mekanizması akıllıca bir optimizasyona gidiyor. Bu, C# compiler’ın işini zamanında yapmasını sağlayan çok akıllı bir optimizasyon. Bu optimizasyon, aynı string’lerin hash code’larının aynı olması gerektiği gözlemine dayanıyor. Bu yüzden string’leri teker teker eşitliğini kontrol etmek yerine, compiler hedef string’in bir hash’ini hesaplıyor table-lookup mantığında çalışmasını sağlıyor yani O(1) zamanda.

Bu Roslyn’in github sayfasında şöyle bahsedilmiş:

The string switch codegen in Roslyn is completely new. Roslyn does not use dictionaries to avoid allocations and a potentially huge penalty when a string switch is execute for the first time. Roslyn uses a private function that maps strings to hash codes and a numeric switch. In some sense this is a partial inlining of the former technic that used static dictionaries.

Kaynaklar:

https://sharplab.io/#v2:EYLgtghglgdgPgAQEwEYCwAoBBmABM3AYVwG9NcL89YAXXAWQAoEUAGXAZwEpdzKyMlIZwDuUGgGMAFo259hpeQsoSIHAKa4ARBC0h8AdlwoA3EuW5VG7cD2HcSM4Isq1mrRLsIj2Jy9fWWgAmXkYALH7+lm7a6qG4AKyR/lbuAGbxAGzJLqnaAObxBjkWQeppEACuADY0+t64ALSm5pQAvkodGG1AA=

https://en.wikipedia.org/wiki/Switch_statement#Advantages_and_disadvantages

https://github.com/dotnet/roslyn/blob/main/src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.Lowered.cs

C# 11 ile Gelen Yenilikler

Microsoft’un yayınladığı blog yazısına istinaden C# 11 ile gelebilecek özelliklere göz attık.

Öncelikle .NET 7 henüz long term support olmadığı için, C# 11’i kullanmak adına bazı ayarlar yapmanız gerekiyor. Bunun için visual studio 2022 17.1 versiyonunu indirmeli (community, professional veya enterprise edition fark etmez) ve .NET SDK’sının 6.0.200 versiyonunu kurmanız gerekiyor. Son olarak ta, .NET 6 ile oluşturduğunuz projenizin csproj dosyasında LangVersion tag’ını preview olarak eklemeniz gerekiyor.

✅ String interpolation’daki yenı satır kısıtı

Bildiğiniz gibi verbatim string literal‘ler içerisinde yeni satırda kullanım sağlayabiliyorduk fakat non-verbatim string literaller içerisinde bunun için \r\n kullanmamız gerekiyordu. C# 11 ile birlikte, non-verbatim interpolated string’ler için de yeni satır kısıtını kaldırmışlar.

var v = $"sayı\t: { 5.tostring()
.ToString(
Cultureınfo.InvariantCulture)}";

✅ List patterns (opsiyonel slice patterns)

Liste ve dizilerde pattern matching desteği geliyor. List pattern’lar köşeli parantezlerle belirtilirken, slice pattern’lar ise iki nokta (..) ile belirtiliyor ve isterseniz var pattern’ı da kullanabiliyorsunuz. İlerleyen zamanlarda IEnumerable tipler için de list pattern desteği getirmeyi planlıyorlarmış.

✅ Parameter null-checking (!! operatörü)

Ve geldik .NET dramasına dönen o yeniliğe. Hem Twitter hem de Github’ta çok fazla tartışıldı bu operatör. Ek olarak  @Sedat Kapanoglu  da bu yeniliği neden beğenmediğini yine aynı thread içerisinde paylaştı.

https://github.com/dotnet/csharplang/discussions/5735#discussioncomment-2153360

Özetle, C#’ta bir argümanın null kontrolü klasik olarak aşağıdaki şekildeydi;

void M1(string s)
{
   if (s is null)
   {
      throw new ArgumentNullException(nameof(s));
   }
}

.NET 6 ile ThrowiIfNull statik metodu geldi.

void M2(string s)
{
   ArgumentNullException.ThrowIfNull(nameof(s));
}

ve C# 11 ile birlikte !! (bang bang) operatörü hayatımıza girecek aynı işlevi gören.

void M3(string s!!)
{
}

Bu arada bu özellik nullable reference types ile birlikte çalışabiliyor. NRT compile time’da, parameter null-checking runtime’da kontrol şeklinde düşünebilirsiniz.

Lambda parametreleri desteği var. Indexer parametreleri için kullanılabilir. Get ve set içerisinde kontrol edilir. Constructor’lar için “field initialization”‘dan önce kontrol ediliyor. async metodlarda da kullanım mevcut.

Kaynak:

https://devblogs.microsoft.com/dotnet/early-peek-at-csharp-11-features/

https://github.com/dotnet/csharplang/discussions/5735

https://sharplab.io/#v2:EYLgtghglgdgPgAQEwEYCwAoBBmABM3AYVwG9NcL8AWXAWRQAoEUAGXAZwEpzKyNKBuKADNcDdkIkwArgBtZ3foIp9lygC4ALAE4B7AO64YAU0MBBbQHNpYYzHUA5ObICiADwDGxgA7qoumAYYCFtdYXFOTgBuHmUAX1jcBIxEgHpU3AA6BxcAFVwANkxEhBpaJCZWDkUBVTULa1t7J3l3L19/GEzcnQMASWEW2SCQ4zCI6MTkkrLsSrZ2AEJFmt4pzDigA=

Visual Studio 2022 17.1 ile gelen yenilikler

Visual Studio 17.1 sürümü 15 Şubat 2022 tarihinde release edildi. Bu videoda bu sürüm ile gelen yeniliklere göz attık.

— Index’lenmiş dosyalar ile daha hızlı arama özelliği geldi. Bunu arka planda task manager ile görebileceğiniz ServiceHub.IndexingService.exe uygulaması ile sağlamaya başladılar. Bu özelliği Tools -- Options -- Environment -- Preview Features -- Enable indexing for faster find experience adımlarından açıp kapatabilirsiniz.

— Kod dosyalarınızı otomatik olarak senkronize etme. Bu özellik Tools -- Options -- Environment -- Documents -- Automatically save files when Visual Studio is in the background adımlarından açıp kapatabilirsiniz. Community edition’da yok sanırım, sadece professional ve enterprise müşterilerde var galiba bu.

— Branch’ler arası karşılaştırma.

C# 11 ile gelmesi planlanan Raw string literal özelliğine otomatik olarak regular string literal veya verbatim string literal’lerden Quick Tips bubble’ı ile çevirme.

Yani;

var s = "\"foo\r\nbar\"";

string’ini;

var s2 = """
    "foo
    bar"
    """;

yapabiliyor. Raw string literal’ler string interpolation’ı destekliyor ve hizalamayı önemsemiyorlar gördüğüm kadarıyla.

— Line staging

Geliştirmesi hala devam ediyormuş. Sanırım bir dosya içerisinde belirli bir satırı stage’e atma işlemi.

— C# 7 – Tuple swap

var temp = args[1];
args[1] = args[0];
args[0] = temp;

kodunu “Quick Actions” ile

(args[0], args[1]) = (args[1], args[0]);

koduna çevirebiliyorsunuz.

— Display diagnostics inline

Bu özelliğe Tools -- Options -- Text Editor -- C# -- Advanced ile gidebiliyorsunuz. Popup ile görebileceğiniz warning’leri ekranda direkt olarak çıkartabiliyor.

Örneğin sadece;

int second = 1;

yazdığınızda, değişkenin üstüne gittiğinizde çıkan popup’ı ekrana direkt olarak basabiliyor. Deneme aşamasında şu anda.

— Simplify property pattern

C# 10 ile gelen extended property patterns özelliğine “Quick Tips” bubble’ı ile otomatik olarak çevirim sağlayabiliyorsunuz.

Yani;

if (t is { Assembly: { EntryPoint: { CallingConvention: CallingConventions.Any } } }) ;

kodunu

if (t is { Assembly.EntryPoint.CallingConvention: CallingConventions.Any }) ;

koduna çevirebiliyoruz.

Kaynaklar:

https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-1-is-now-available/

https://docs.microsoft.com/en-us/visualstudio/releases/2022/release-notes

Microsoft Mülakat Sorusu | Insertion Sort List

Leetcode içerisinde bulunan “Insertion Sort List” sorusunun açıklaması ve çözümü. Bu soruda size verilen linked list içerisindeki node’ları insertion sort kullanarak sıralamanız isteniyor.

➡️ Leetcode 147. Insertion Sort List: https://leetcode.com/problems/insertion-sort-list/

➡️ Problem açıklaması:

Given the head of a singly linked list, sort the list using insertion sort, and return the sorted list’s head. The steps of the insertion sort algorithm:

– Insertion sort iterates, consuming one input element each repetition and growing a sorted output list.

– At each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list and inserts it there.

– It repeats until no input elements remain.

The following is a graphical example of the insertion sort algorithm. The partially sorted list (black) initially contains only the first element in the list. One element (red) is removed from the input data and inserted in-place into the sorted list with each iteration.

Example 1:

Input: head = [4,2,1,3]

Output: [1,2,3,4]

Example 2:

Input: head = [-1,5,3,4,0]

Output: [-1,0,3,4,5]

Constraints:

The number of nodes in the list is in the range [1, 5000].

-5000 <= Node.val <= 5000