Split a List into Sublists of Size N

How do you write a code in C# to split the list [a, b, c, d, e, f, g, h] into sublists [a, b, c], [d, e, f], [g, h] each with three elements and the last with less than three? The most popular answer is the following LINQ.

In StackOverflow, this LINQ got more than 900 upvotes as of the answer to two questions (Split a List into smaller lists of N size [duplicate], Split List into Sublists with LINQ).

However, this method has the worst performance in any assumed answers. It creates the same number of objects with Index and Value as the length of the source. Object creation is a costly operation in terms of both memory and speed. Although the cost is much smaller, the exact count of divisions and comparisons as the length of the source is also not good for performance.

If you need performance, you should not use LINQ in the first place, but if you insist on a concise LINQ, how about the following solution.

The following are the benchmark results taken from BenchmarkDotNet, which splits a 1000-length array of ints into three pieces each. The first answer is Splitter1, and the above is Splitter2. Mean is the average, and the rests are measurement errors. The results show Splitter2 was more than 3.5 times faster than Splitter1.

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19044.1766 (21H2)
AMD Ryzen 7 3800X, 1 CPU, 16 logical and 8 physical cores
.NET SDK=6.0.106
  [Host]  : .NET 6.0.6 (6.0.622.26707), X64 RyuJIT
  LongRun : .NET 6.0.6 (6.0.622.26707), X64 RyuJIT

Job=LongRun  IterationCount=100  LaunchCount=3  
WarmupCount=15  
MethodMeanErrorStdDev
Splitter189.94 μs0.351 μs1.779 μs
Splitter224.04 μs0.100 μs0.517 μs

If the target framework of your projects is .NET 6 or later, you should use the Chunk method for this operation, which is introduced in .NET 6. The benchmark results, including the Chunk method, are shown below. It was more than 4,000 times faster than Splitter2.

MethodMeanErrorStdDev
Splitter188,650.102 ns245.2557 ns1,251.8625 ns
Splitter223,481.503 ns117.8934 ns600.6975 ns
Chunk5.609 ns0.0198 ns0.0984 ns

The dotnet format command and StyleCop.Analyzers

This article explains how to use the dotnet format command with .editorconfig and its limitations and then shows you that StyleCop.Analyzers can overcome them. This article also mentions how to apply the StyleCop ruleset to all projects in a solution.

Continue reading "The dotnet format command and StyleCop.Analyzers"

How to Make Good Commits

This article explains how to make good commits in version control systems such as git. This article will show you the following topics.

  • The purposes of creating commits
  • How to make good commits for each purpose
  • How to write good commit messages
  • Anything easily found by searching "git commit message."

The purposes of making commits

Software development is a process of continually changing artifacts (documentation, source code, etc.) over time. Version control systems, including git, manage those changes and allow us to capture a moment in between the time by a commit.

There are three purposes to capture a specific moment.

The first purpose is to preserve the moment when the software is working correctly. If a bug occurs in changes from that moment, you can go back to the previous commit to recover the working state. If you find a bug in a commit that should work, you can go back to one more commit. If you don't find the same bug there, you can identify that the bug occurred in the next commit.

The second purpose is to place a message at a moment and record it. The message helps you remember the reason for the change in the commit afterward, and other people can understand your work by investigating your commits.

The third purpose is to decide when to share your changes with the team members. In version control systems, you need to make commits to share your changes with others; in git, you need to push them to a shared repository, but whatever the case, you need commits to share your changes with others.

Good commits

Thinking about the purpose of a commit makes it easier to understand how to make a good commit, i.e., which moment of the ever-changing artifacts you should capture.

Commits to capture the working states

You should make a commit that preserves the working state and helps us track down bugs when you can assume the software works properly. You should try not to have more than one bug in a commit to make it easy to identify which commit a bug resides.

A perfect moment to make a commit is the next time the software works correctly, after making small changes that are unlikely to introduce multiple bugs from the previous commit.

From this point of view, a commit with absolutely no room for bugs is useless because it only adds another step when you track down a bug. It's really unnecessary if it doesn't meet other purposes described below.

Commits to place messages on certain moments

Of course, a commit to place a message at a specific moment should be made when there are no changes unrelated to the message. And the message must make it easy to understand the commit both for you and others.

The message should have one thing. So, if it is something like "A and B", the commit should be divided into two. And the message should be concrete enough to narrow the changes included by the commit.

A commit with a few thousand lines of changes represented by a vague message is not helpful to anyone. On the other hand, even if a commit has thousands of lines of changes, it is still helpful if it has a concrete message like "Change the method name A to B".

Commits to share changes with other members

When you make a commit to tell other members about your changes, it is even more important to place a concrete message and make the changes small. Since you are asking another member to review your commit, you should not make the commit something even you don't feel like reviewing. Of course, if there are team rules about commits, you have to follow them.

You should make such a commit when the development process in your team requires it. For example, if your team uses an issue management system, such as GitHub issue, you need to create a commit when you solve the issue assigned to you, and you must follow the rules in your team to tie your commit to the issue.

Good commit messages

Because a commit is a snapshot of a moment, the accompanying message should either describe the changes that occurred between last and this time, describe the event that triggered the snapshot, or both.

You should summarize a commit in the first line of the message. Because many version control systems, including git, only show the first line of the message on the commit log in the briefest format. This format provides a bird' eye view of the many commits and becomes more valuable by good first-line summaries.

In git, there is a convention requiring us to write one line summary with less than 50 characters at the first line. It's a good practice. Though the line can be longer than 50 characters, it shouldn't be too long because humans have a limit of how many characters they can read at a glance.

On a version control system in your team, your commit messages are messages to other members, and the commit log is an essential component of communication in the team. The commit log is like a bulletin board to help the communication, and the messages placed on it should be brief and to the point.

A suitable manner of writing a message depends on the product being developed and the team developing the product. Still, you should note "what has been done" in an imperative form, "do something" to summarize your changes. The candidates as the verb are shown below.

  • Add
  • Implement
  • Create
  • Fix
  • Update
  • Change
  • Improve
  • Remove/Delete
  • etc.

Examples of messages are "Fix bug in the signature algorithm.", "Improve speed of displaying the user list.", "Update models to reflect changes in the company table", "Change ConnectionCreator to ConnectionBuilder".

As many projects are doing, prefixing a message with one or more tags to identify the related issue, module, or subsystem, can help narrow down the scope of the "what" in a short number of characters.

If this is necessary and you can keep it short, you may add "what for". If the message becomes too long, you can move the details to the second line (the third line after a blank line in git) or later. And for a commit tied to an issue on an issue management system, you can leave the details in the comments of the corresponding issue.

Conclusion

I started by explaining the purposes of commits and showed you how to make good commits. By the way, I wrote this article to encourage my current team members to improve the granularity of commits and the quality of their messages. Many sentences started with "you should do," but most of them mean just "I would like my team members to do," so please forgive me for that.

Equality Comparison of Floating-Point Numbers in C# (and Others)

tl;dr

You should compare two floating-point numbers for equality in C# as follows:

tolerance must be much larger than double.Epsilon.

Continue reading "Equality Comparison of Floating-Point Numbers in C# (and Others)"

Implementing a System Tray App with WPF and MVVM

This article illustrates the implementation of a system tray application with WPF and the MVVM pattern. The full source code is in the GitHub repository.

The implementation has two distinctive points. First, it does not use notable WPF NotifyIcon because the license, CPOL, isn't compatible with any OSS licenses. Then, the implementation obeys the MVVM pattern and has no code behind.

Continue reading "Implementing a System Tray App with WPF and MVVM"

Quite Simple Memory Pool in C#

This article shows a quite simple memory pool to make a thread-unsafe library thread-safe without performance degradation in single-threaded programs. Same as the previous article, this article is about DynaJson.

Thread-safety requires overhead to allocate an instance by each invocation to isolate data being altered. Unless thread-safety is required, we can use a static class or a singleton to eliminate any additional allocation.

Continue reading "Quite Simple Memory Pool in C#"

[Unity] How to Use Physics.OverlapCapsule

Updated on 2021-09-06: This article was largely revised to take into account the rotation of the attached game object and the direction of the CapsuleCollider.

Capsule and Cube Collider

You can use Physics.OverlapCapsule to get the two Colliders overlapped with the CapsulCollider as above. This method takes the position and the size of a capsule and returns all Colliders overlapped by the capsule.

Continue reading "[Unity] How to Use Physics.OverlapCapsule"