This is part 3 of the C# tips and tricks you can find the links below
part 1: https://dev.to/moe23/c-tips-and-tricks-part-1-3jj9
part 2: https://dev.to/moe23/c-tips-and-tricks-part-1-2hm1
In this article we will be covering:
- Async Main
- Tuples
- Value Equality for a class
You can watch the full video on YouTube
You can get the source code on GitHub:
https://github.com/mohamadlawand087/v35-ctte3
Async Main
This will allow us to add the async word into our main entry point, we can utilise it for
When we want to run async method from the main method, previously we could not await the main method. We need to do alot of wiring to make it work
So previously we need to something like this
static void Main(string[] args)
{
// Old implementation - utilise the Async method
var result = DoAsyncWork().GetAwaiter().GetResult();
Console.WriteLine(result.ToString());
}
// Have an async method
private static async Task<string> DoAsyncWork()
{
return await new HttpClient().GetStringAsync("https://docs.microsoft.com");
}
New implementations
static async Task Main(string[] args)
{
// New implementation - Direct call to async
var res = await new HttpClient().GetStringAsync("https://docs.microsoft.com");
Console.WriteLine(res.ToString());
}
Tuples
a light wait syntex used to represent data. With tuples we remove the complexity of having classes and records. We can define simple data structure with multiple feilds using tuples.
There is 2 types
- Name tuple
- Unnamed tuple
Although its a light weight syntax, it has really powerfull features that we can utilise
Named tuple where we specify the name of the field, so we declare a name variable. Now that i have specified the name of the field i can use it and refer to it when i utilise the tuple
// Name Tuple
var named = (FirstName: "Mohamad", LastName: "Lawand");
Console.WriteLine($"{named.FirstName}, {named.LastName}");
Unnamed tuple, we are not giving a name for each feild and we utilise the generic way of calling the feilds inside the tuple by using item1 item 2
// Unamed Tuple
var unnamed = ( "one", "two");
Console.WriteLine($"{unnamed.Item1}, {unnamed.Item2}");
As well with tuple we can run equaliy operators
var item1 = (x: 23, y: 40);
var item2 = (x: 23, y: 40);
// utilising the equality operator
Console.WriteLine(item1 == item2);
So basically it recognise what is this object and the data model of the object and all of the fields in it and still gives us the ability to compare.
How to define value equality for a class
When we define a class or struct, you decide whether it makes sense to create a custom definition of value equality (or equivalence) for the type. Typically, we implement value equality when we expect to add objects of the type to a collection, or when their primary purpose is to store a set of fields or properties.
Our implementation should follow the five guarantees of equivalence (for the following rules, assume that x
, y
and z
are not null):
- The reflexive property:
x.Equals(x)
returnstrue
. - The symmetric property:
x.Equals(y)
returns the same value asy.Equals(x)
. - The transitive property: if
(x.Equals(y) && y.Equals(z))
returnstrue
, thenx.Equals(z)
returnstrue
. - Successive invocations of
x.Equals(y)
return the same value as long as the objects referenced by x and y aren't modified. - Any non-null value isn't equal to null. However,
x.Equals(y)
throws an exception whenx
is null. That breaks rules 1 or 2, depending on the argument toEquals
.
class Bus : IEquatable<Bus> {
public string Name { get; private set; } // init
public string Color { get; private set; } // init
public Bus(string name, string color)
{
if(string.IsNullOrEmpty(name))
{
throw new ArgumentException("Bus must have a name");
}
Name = name;
Color = color;
}
public override bool Equals(object obj) => this.Equals(obj as Bus);
public bool Equals(Bus b)
{
if(b is null)
{
return false;
}
if(Object.ReferenceEquals(this, b))
{
return true;
}
if(this.GetType() != b.GetType())
{
return false;
}
return (Name == b.Name) && (Color == b.Color);
}
public static bool operator == (Bus b1, Bus b2)
{
if(b1 is null)
{
if(b2 is null)
{
return true;
}
return false;
}
return b1.Equals(b2);
}
public static bool operator !=(Bus b1, Bus b2) => !(b1 == b2);
}
var busA = new Bus("School Bus", "Yellow");
var busB = new Bus("School Bus", "Yellow");
var busC = new Bus("Public Transport", "Red");
Bus busD = null;
Console.WriteLine($"busA.Equals(busB): {busA.Equals(busB)}");
Console.WriteLine($"busA == busB : {busA == busB}");
Console.WriteLine($"busA.Equals(busD) {busA.Equals(busD)}");
Console.WriteLine($"busA.Equals(busC): {busA.Equals(busC)}");
Console.WriteLine($"busA == busC : {busA == busC}");
Top comments (0)