If you have taken a call to grow your career in the information technology sector, knowledge of coding is essential. It is the most in-demand skill in the industry. Thus, the programming knowledge you gain and practice, in the beginning, is priceless.
Here are more than 15 good C# tips and tricks for these 2022 that will be of great help to you!
Nullable number
This tip is based on knowing that numbers CAN accept nulls. This tip is strange for many developers of other languages because we will use the symbol ?
after the data type.
In this case we will use int
but first let’s see what it would look like without the symbol ?
👇
using System;
namespace bytehide
{
class Program
{
static void Main(string[] args)
{
int number = null;
Console.WriteLine(number);
}
}
}
If we simply copy and paste this code, when executed it generates an error as you can see in the following image 👇
Now we will simply add the symbol ?
toint
to look like int?
.
Let’s see how the code would look like 👇
using System;
namespace bytehide
{
class Program
{
static void Main(string[] args)
{
int? number = null;
Console.WriteLine(number);
}
}
}
Now let’s run it again and see what happens 👇
Good! It has worked, it has not returned any error and if we check the value of number
we can indeed see that yes, it is null.
Readonly value
In a field statement, readonly
indicates that the assignment to a field can only occur as part of the declaration or in a constructor of the same class. That is, READ ONLY.
Based on this, let’s see how it works with this example 👇
using System;
namespace bytehide
{
class Program
{
public static readonly string Url = "www.bytehide.com";
}
}
Here we can simply see that the Url
value is “ByteHide.com”.
But… what if we try to change it later, is it possible? Let’s find out 👇
using System;
namespace bytehide
{
class Program
{
public static readonly string Url = "www.bytehide.com";
static void Main(string[] args)
{
Url = "";
}
}
}
We tried to change the Url
value to null and no, it didn’t let us 👇
An example of use of readonly is in the connection to a database since it is always the same and we are not interested that nobody can change it.
Readonly is curious because if it is supposed to be a variable that can only be read and not modified… Could the definition of constant be applied to it?
Detect null strings
In this tip we are going to see how we can detect if a string is null or not null. For this we are going to reuse the example of the previous tip 👇
using System;
namespace bytehide
{
class Program
{
public static readonly string Url = "www.bytehide.com";
static void Main(string[] args)
}
}
Now we are going to use sting.IsNullOrEmpty
. This checks strings for references to null or empty strings. We simply return in console if it is null or not null 👇
using System;
namespace bytehide
{
class Program
{
public static readonly string Url = "www.bytehide.com";
static void Main(string[] args)
{
if (string.IsNullOrEmpty(Url))
Console.WriteLine ("This string is null or empty.");
else
Console.WriteLine("This string is not null or empty.");
}
}
}
And if we execute we can see that it returns that it is not empty (as its value is “ByteHide.com”) 👇
Terminate application
Here we are going to see a very simple way for the application to exit its execution when a condition is met. Let’s see the example that we are going to use 👇
using System;
namespace bytehide
{
class Program
{
static void Main(string[] args)
{
int number = 1;
if (number == 1)
{
Console.WriteLine("Exit");
}
Console.WriteLine("No exit");
}
}
}
At this point I want that when the condition is met (which is met), the application exits its execution. So we will use Environment.FailFast
and exit with the indicated argument: “Successfully exited” 👇
using System;
namespace bytehide
{
class Program
{
static void Main(string[] args)
{
int number = 1;
if (number == 1)
{
Console.WriteLine("Exit");
Environment.FailFast("Successfully exited");
}
Console.WriteLine("No exit");
}
}
}
When running it, we can indeed see that the application exits its execution correctly.
Line break
Who is not accustomed to making line breaks with /n
? 🤔
Well, in C# there is a special way to make them. For it, inside the environment
class we have NewLine
👇
using System;
namespace bytehide
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"First{Environment.NewLine}Second");
}
}
}
With this we will have a line break. Let’s run to check it 👇
Write unit tests for non-public methods
Surely if you work with projects that require quality control you have had to introduce a test project that involves unit tests. In that case, you have probably had problems trying to try a method that is not public.
C# allows internal assemblies to be made visible to other assemblies. To solve it we will add the following attribute in the AseemblyInfo.cs.
// Make a specific assembly visible
assembly: InternalsVisibleTo("MyTestAssembly")]
Use tuples
Sometimes it is better to use a containing tuple of typed values than to use classes, especially when the data structure created is only going to be used at a specific moment.
public Tuple<int, string, string> GetEmployee()
{
int employeeId = 100;
string firstName = "John";
string lastName = "Smith";
//create a tuple and return it
return Tuple.Create(employeeId, firstName, lastName);
}
No need to create temporary collections, better to use yield
We usually create enumerable temporary structures to return in a method.
Something similar to the following:
public List<int> GetValuesGreaterThan100(List<int> masterCollection)
{
List<int> tempResult = new List<int>();
foreach (var value in masterCollection)
{
if (value > 100)
tempResult.Add(value);
}
return tempResult;
}
In these cases we can save a couple of lines of code by using the yield command.
Next we show the previous example but using yield:
public IEnumerable<int> GetValuesGreaterThan100(List<int> masterCollection)
{
foreach (var value in masterCollection)
{
if (value > 100)
yield return value;
}
}
Report that the method is obsolete
If your library is being used by different clients and you want some method to stop being used because there is another method that replaces them or simply because it no longer works, you can indicate it with the following attribute:
[Obsolete("This method will be obsolete soon. To replace it you can use the XYZ method.")]
public void MyComponentLegacyMethod()
{
// Here the implementation
}
The above code would cause a warning in the code that invokes this method. However, if you want it to no longer be usable in any way, you would use an additional Boolean parameter such as True.
[Obsolete("This method will be obsolete soon. To replace it you can use the XYZ method.", true)]
public void MyComponentLegacyMethod()
{
// Here the implementation
}
Remember that linq queries are deferred
When a query is made in linq it only actually runs when the results are accessed. This is called deferred execution. In order for the query to be executed only once, we must use the ToList method.
public void MyComponentLegacyMethod(List<int> masterCollection)
{
// Without the ToList method, this LINQ query would be executed twice
var result = masterCollection.Where(i => i > 100).ToList();
Console.WriteLine(result.Count());
Console.WriteLine(result.Average());
}
Converting Business Entities Using the Explicit Keyword
Use Explicit to define entity conversion. The conversion method will be called when needed.
An example:
class Program
{
static void Main(string[] args)
{
ExternalEntity entity = new ExternalEntity()
{
Id = 1001,
FirstName = "Dave",
LastName = "Johnson"
};
MyEntity convertedEntity = (MyEntity)entity;
}
}
class MyEntity
{
public int Id { get; set; }
public string FullName { get; set; }
public static explicit operator MyEntity(ExternalEntity externalEntity)
{
return new MyEntity()
{
Id = externalEntity.Id,
FullName = externalEntity.FirstName + " " + externalEntity.LastName
};
}
}
class ExternalEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Keep the original Stack Trace
In .NET, when a catch block is used to catch an exception and it is thrown again, information is lost since it is understood that it has been handled and that the exception is generated from the block that caught it.
Example:
public void RunDataOperation()
{
try
{
Intialize();
ConnectDatabase();
Execute();
}
catch (Exception exception)
{
throw exception;
}
}
To keep the original trace of the error we will do this:
public void RunDataOperation()
{
try
{
Intialize();
ConnectDatabase();
Execute();
}
catch (Exception)
{
throw;
}
}
Flags Attribute — Enum Grouping
Using the Flags attribute within an enumeration will allow you to group the enum values.
class Program
{
static void Main(string[] args)
{
int snakes = 14;
Console.WriteLine((Reptile)snakes);
}
}
[Flags]
enum Reptile
{
BlackMamba = 2,
CottonMouth = 4,
Wiper = 8,
Crocodile = 16,
Aligator = 32
}
Force the base type for a generic type
Let’s start from the fact that we have created a generic class where it must be fulfilled that the generic type provided in the class must inherit from a specific interface, this can be done as shown in the following example:
class MyGenricClass<T> where T : IMyInterface
{
// Class body would go here
}
Or even at the method level:
class MyGenericClass
{
public void MyGenericMethod<T>(T t) where T : IMyInterface
{
// Generic implementation would go here
}
}
Exposing a property as IEnumerable does not make it read-only
Let’s imagine that we create a class with a property of type IEnumerable, in this case it is possible to modify this property even if it is read only.
An example:
class Program
{
static void Main(string[] args)
{
MyClass myClass = new MyClass();
((List<string>)myClass.ReadOnlyNameCollection).Add("######From Client#####");
myClass.Print();
}
}
class MyClass
{
List<string> _nameCollection = new List<string>();
public MyClass()
{
_nameCollection.Add("Rob");
_nameCollection.Add("John");
_nameCollection.Add("Jummy");
_nameCollection.Add("Derek");
}
public IEnumerable<string> ReadOnlyNameCollection
{
get { return _nameCollection.AsEnumerable(); }
}
public void Print()
{
foreach (var item in ReadOnlyNameCollection)
{
Console.WriteLine(item);
}
}
}
In the previous code we have been able to verify that the list could be modified when our intention is to read it only.
To remedy this we can use the following:
public IEnumerable<string> ReadOnlyNameCollection
{
get { return _nameCollection.AsReadOnly(); }
}
Writing efficient code isn’t always easy, but it can be done. Here are five ways to program more efficiently in C#, no matter what your preferred programming environment is. Whether you use Microsoft Visual Studio or another IDE, this advice will help you quickly, easily, and efficiently improve your programming skills.
At first they may seem like very basic and absurd tips and advice but I know that many C# developers do not put them into practice and end up wasting much more time than expected just reading and trying to understand the code (and if that time has not come, it will come soon).
Most of all, though, these tips will help you save time and minimize errors along the way. In order to succeed at your job as a programmer, you need to make the most of your time — and these tips will help you do just that!
Take advantage of the record types
A very simple way to simplify your C# code when programming is to use record
types. These provide a very easy to read way to create objects, especially in the immutable representation.
Bad way:
//A lot of code lines
public class ApplicationInfo
{
public string Name { get; init; }
public string Path { get; init; }
public ApplicationInfo(string name, string path)
{
Name = name;
Path = path;
}
}
Good way:
//Only one line with record types
public record ApplicationInfo(string name, string path);
This way you will save many lines of code and make it easier to read. If by chance in a few months you or another developer reads that code, you will understand it much easier.
📚Check out the Microsoft article to learn more: Create record types
Avoid poor object initialization
This is another practice that many developers overlook. If properties are not defined between braces, reading that code becomes difficult and this can lead to a longer time to understand that code.
Bad way:
//Poor code format for reading
bytehide securityManger = new bytehide();
securityManger.FindVulnerabilities = true;
securityManger.AppName = "Shield.exe";
Good way:
//Better code format for reading
var securityManger = new bytehide {
FindVulnerabilities = true,
AppName = "Shield.exe"
};
In this case, as you can see, the solution is simple. Use object and collection initializers to allow a better reading of the code.
📚Check out the Microsoft article to learn more: Object and Collection Initializers
Get used to using Var to define variables
Developers often complicate ourselves by using types that are too specific when defining variables. This can only lead to confusion when it comes to understanding the code.
Bad way:
//Difficult to read
List<Repository.Shield.SecureDependencies> listOfSecureRefs = _repo.Shield.LastDependenciesAnalyzed();
Good way:
//Easier to read
var listOfSecureRefs = _repo.Shield.LastDependenciesAnalyzed();
To solve this bad practice, it is as easy as using var
keyword. This way the final code will be cleaner and much faster to read.
📚Check out the Microsoft article to learn more: Implicitly typed local variables
String interpolation “$” instead string.Format()
String.Format()
is a common method of inserting values from one string into another but it is not the cleanest or the best if we focus on clean code.
Bad way:
//using string.Format()
var date = DateTime.Now;
string greetings = string.Format("Today is {0}, the time is {1:HH:mm} now.", date.DayOfWeek, date);
Good way:
//using string interpolation
var date = DateTime.Now;
string greetings = $"Today is {date.DayOfWeek}, the time is {date:HH:mm} now.");
We see that by string interpolation the resulting code is much more readable. This is an example with a very simple code. In much more complex real life cases, you will appreciate having the code organized and clean.
📚Check out the Microsoft article to learn more: $ — string interpolation
Null coalescing (??) instead if-else
At first glance, using nested if-else
seems to be the simplest option for null checking. Although it is a simple option, it is not the best one.
Bad way:
if (application != null)
{
if (application.protected != null)
{
return application.protected.shieldLastRun;
}
else
{
return string.empty;
}
}
else
{
return string.empty;
}
Good way:
return application?.protected?.shieldLastRun ?? string.empty;
By using the null coalescing operator ??
we can greatly reduce the number of lines of code and make it easier to read.
📚Check out the Microsoft article to learn more: ?? and ??= operators