chevron_left chevron_right
Login Register invert_colors photo_library


Stay updated and chat with others! - Join the Discord!
Thread Rating:
  • 0 Vote(s) - 0 Average


Tutorial C# - An introduction to time saving shortcuts filter_list
Author
Message
C# - An introduction to time saving shortcuts #1
It seems like many members here are getting into C#, and since I use it on a daily basis for work, I figured I'd give you guys examples of some of the cool features you get from C# that you don't get from other languages.

1. Coalesce operator

How many times have you had some nested class or struct, where some of the properties were nullable? Take this one for example:
Code:
class test_root
{
    public class test_lvl1
    {
        public int a;
    }
    public string somestr;
    public test_lvl1 test;
    public test_lvl1 alternate;
}

Now, in your program, you would prefer to get .a from test, but if that doesn't exist, you'd like to get it from alternate. You're probably thinking of writing this:
Code:
test_root r = new test_root();
r.somestr = "whatever";
r.alternate = new test_root.test_lvl1();
r.alternate.a = 5;

if (r.test == null)
    Console.WriteLine(r.alternate.a);

this works, but it gets exponentially more complicated as you get deeper in levels, I'm sure you can see that. With the coalesce operator though, you don't have to write all of these checks. The following code works the same:
Code:
test_root r = new test_root();
r.somestr = "whatever";
r.alternate = new test_root.test_lvl1();
r.alternate.a = 5;

Console.WriteLine((r.test ?? r.alternate).a);

That double question mark is the coalesce operator. What it does is, if the object on the left of it is null, then it will use the object on the right instead.


2. Null-conditional operator

Let's go back to the above example, but this time we'll add some more levels:
Code:
class test_root
{
    public class test_lvl1
    {
        public class test_lvl2
        {
            public double b;
        }
        public int a;
        public test_lvl2 lvl2_primary;
        public test_lvl2 lvl2_secondary;
    }
    public string somestr;
    public test_lvl1 primary;
    public test_lvl1 alternate;
}

and we'll initialize it like so
Code:
test_root r = new test_root();
r.somestr = "whatever";
r.primary = new test_root.test_lvl1();
r.primary.a = 1;
r.primary.lvl2_secondary = new test_root.test_lvl1.test_lvl2();
r.primary.lvl2_secondary.b = 2.72;
r.alternate = new test_root.test_lvl1();
r.alternate.a = 5;
r.alternate.lvl2_primary = new test_root.test_lvl1.test_lvl2();
r.alternate.lvl2_primary.b = 3.14;

and now, let's say our code needs to follow this order in getting the .b double value:
  1. Primary value from primary lvl1
  2. Primary value from alternate lvl1
  3. Secondary value from primary lvl1
  4. Secondary value from alternate lvl1
Sure again here we can use if statements, and that might look something like this:
Code:
if (r.primary != null && r.primary.lvl2_primary != null)
    Console.WriteLine(r.primary.lvl2_primary.b);
else if (r.alternate != null && r.alternate.lvl2_primary != null)
    Console.WriteLine(r.alternate.lvl2_primary.b);
else if (r.primary != null && r.primary.lvl2_secondary != null)
    Console.WriteLine(r.primary.lvl2_secondary.b);
else if (r.alternate != null && r.alternate.lvl2_secondary != null)
    Console.WriteLine(r.alternate.lvl2_secondary.b);
else
    Console.WriteLine("No valid values");
but not only is that ugly, it's just a pain in the ass to write...
Now it's time to introduce the null-conditional operator. Whenever you're accessing a member on an object, if you place a question mark before the dot, then C# will stop evaluating at that point if the object is null. What this means is we don't have to do a bunch of error handling, and can just get on with our lives. We can then combine the coalesce operator in such a way that we can reduce this down to the bare minimum number of lines.
Code:
Console.WriteLine(((r.primary?.lvl2_primary ?? r.alternate.lvl2_primary) ?? (r.primary?.lvl2_secondary ?? r.alternate?.lvl2_secondary))?.b.ToString() ?? "No valid values");
I'm deliberately not going to break that down and explain each component of it, but I will explain the very first bit:
Code:
r.primary?.lvl2_primary
this evaluates to something like:
Code:
test_root result;
if (r.primary == null)
    result = null;
else
    result = r.primary;
In conclusion, by making use of the null-conditional operator and coalesce operators, we've managed to turn 10 lines of if-elseif-else into 1 single line.

3. inline declarations
Any serious C# programmer isn't running Convert.ToInt32 on user-entered input (or if they are, there's a pile of exception handlers involved). No, we're using int.TryParse. Unfortunately though, that method doesn't return our number, it returns bool. So we have to pass in our desired result as an out parameter. This means we need to waste a line declaring it, right? Well, no. This one is going to be the shortest in this list, but you can actually declare those right in your function call. The following is totally valid code:
Code:
if (int.TryParse(Console.ReadLine(), out int result))
    Console.WriteLine(result);

4. returning multiple parameters
Have you ever had a lambda function that you're writing and you need to return more than one parameter? It's a lambda, so out parameters are out of the question, you wind up wrapping things into a new class that's just used for that one lambda. Turns out you don't need to do any of that. C# can create a tuple for you on the backend (with as many values as you want), and then deconstruct that into the callee. The best context for this is doing some background work and then returning to the UI thread to update the screen. Let's look at an example:
Code:
Task.Run(() =>
{
    // code running in the background
    int a = 5;
    int b = 7;
    return a - b;
}).ContinueWith(t =>
{
    if (!t.IsFaulted)
    {
        // running on the UI thread
        Console.WriteLine(t.Result);
    }
}, TaskScheduler.FromCurrentSynchronizationContext());
but what if, instead of doing something like that, we want to generate 2 random numbers, sleep the background thread a random number of seconds between the two numbers, and then return those 3 numbers back so they can be shown on screen? Well, thankfully we actually can do this.
Code:
Task.Run(async () =>
{
    // code running in the background
    Random rng = new Random();
    int a = rng.Next(1, 25), b, sleepfor;
    while ((b = rng.Next(2, 30)) >= a) ;
    sleepfor = rng.Next(a, b);
    await Task.Delay(1000 * sleepfor);
    return (a, b, sleepfor);
}).ContinueWith(t =>
{
    if (!t.IsFaulted)
    {
        // running on the UI thread
        (int a, int b, int sleepfor) = t.Result;
        Console.WriteLine($"a: {a}, b: {b}, slept for {sleepfor} seconds");
    }
}, TaskScheduler.FromCurrentSynchronizationContext());
You'll see that simply wrapping our parameters in parenthesis will allow C# to appear as if you're returning multiple values. What you're really getting is Tuple<int,int,int>, but at least this way, you don't have to worry about managing placement, names, etc.


5. String interpolation
And to round this tutorial out, you may have noticed the writeline in the above final example. What does that dollar sign mean? Well, what's written there:
Code:
Console.WriteLine($"a: {a}, b: {b}, slept for {sleepfor} seconds");
is equivalent to
Code:
Console.WriteLine("a: {0}, b: {1}, slept for {2} seconds", a, b, sleepfor);
placing a dollar sign in front of your string tells C# to treat it as if it were String.Format, and replace whatever is within the brackets with it's evaluation.

Well, hope you guys enjoyed, if you did, please let me know.

[+] 1 user Likes phyrrus9's post
Reply

RE: C# - An introduction to time saving shortcuts #2
So simple, yet so effective. I'm by no means a hardcore coder, but there's certainly many of your tips which can be applied to all areas in programming which is incredibly good!

Nice to see you active again Smile


Ransomware is more about manipulating vulnerabilities in human psychology than the adversary’s technological sophistication.

Reply

RE: C# - An introduction to time saving shortcuts #3
Nice tutorial, I've currently ended my last year in college (i'm studying Cyber Security) and the languages I learned were C#, PHP, Powershell and Python.
But the C# they learned me looks way different than yours? Here's an example:

Code:
Console.WriteLine("Which sentence do you want to convert to a PigLatin?");
            string s = Console.ReadLine();
            Console.Write("Your sentence: " + s + "\n");

            string[] array = s.Split(' ');

            for (int i = 0; i < array.Length; i++)
            {
                string FirstLetter = array[i].Substring(0, 1);
                if (FirstLetter == "a" || FirstLetter == "e" || FirstLetter == "o" || FirstLetter == "u" || FirstLetter == "i")
                {
                    string new_word = array[i] + "way";
                    Console.Write(new_word + " ");
                }
                else
                {

                    string new_word = array[i].Substring(1, array[i].Length - 1) + array[i].Substring(0, 1) + "ay";
                    Console.Write(new_word + " ");

                }

            }
            Console.ReadLine();
(This post was last modified: 07-28-2019, 10:55 PM by Malcom.)
As long as you are living, you will face problems. But you serve a God who solves problems.

Reply

RE: C# - An introduction to time saving shortcuts #4
(07-28-2019, 10:55 PM)Malcom Wrote: Nice tutorial, I've currently ended my last year in college (i'm studying Cyber Security) and the languages I learned were C#, PHP, Powershell and Python.
But the C# they learned me looks way different than yours? Here's an example:

Code:
Console.WriteLine("Which sentence do you want to convert to a PigLatin?");
            string s = Console.ReadLine();
            Console.Write("Your sentence: " + s + "\n");

            string[] array = s.Split(' ');

            for (int i = 0; i < array.Length; i++)
            {
                string FirstLetter = array[i].Substring(0, 1);
                if (FirstLetter == "a" || FirstLetter == "e" || FirstLetter == "o" || FirstLetter == "u" || FirstLetter == "i")
                {
                    string new_word = array[i] + "way";
                    Console.Write(new_word + " ");
                }
                else
                {

                    string new_word = array[i].Substring(1, array[i].Length - 1) + array[i].Substring(0, 1) + "ay";
                    Console.Write(new_word + " ");

                }

            }
            Console.ReadLine();

Not to be overly harsh, but if you studied cyber security and you didn't cover C, then you got robbed. On top of that, universities today don't teach their students to innovate, they just teach them to pass the tests and maintain the accreditation of the school so that it can continue making money. You'll get better at C# with time, and what you have looks like perfectly fine C# code, but it's not efficient or easy to read. It's a good starting point, you should focus your efforts on the following:

1. removing unnecessary lines of code
2. getting rid of adding things to strings
3. efficiency in both memory and CPU cycles
4. simplicity
5. error handling. IMO, if you write code that doesn't even need additional error checks (use C#'s built ins to your advantage), you're on the right path.

[+] 2 users Like phyrrus9's post
Reply

RE: C# - An introduction to time saving shortcuts #5
@Malcom  here's an example of a single function taken from an in-production product:

Code:
        public void RefreshUI(FilterItem filter = null, bool? refreshCaches = null)
        {
            currentFilter = filter;
            btnAddItem.IsVisible = filter == null || (filter.IsType && AllowedUploads.Contains(filter.TypeID ?? AllowedUploads.First()));
            if (filter == null)
            {
                if (refreshCaches != true)
                {
                    if (Device.RuntimePlatform == Device.Android)
                        actSpinner.IsVisible = true;
                    else
                        lstFilters.BeginRefresh();
                }
                Task.Run(async () =>
                {
                    if (!refreshCaches.HasValue)
                        refreshCaches |= (Services.Common.Settings().LastLib2CacheRefresh ?? DateTime.UtcNow.AddDays(-2)).AddHours(30) < DateTime.UtcNow;
                    if (refreshCaches == true)
                        await Cache.Library2.Rebuild();
                    Task<List<string>> tagsTask = Cache.Library2.Tags.List();
                    Task<List<ClientModels.v1.LibItem.ItemType>> typesTask = Cache.Library2.ItemTypes.List();
                    return (Tags: await tagsTask, Types: await typesTask);
                }).ContinueWith(async (rvtask) =>
                {
                    (List<string> Tags, List<ClientModels.v1.LibItem.ItemType> Types) = await rvtask;
                    lstFilters.ItemsSource = (Tags ?? new List<string>())
                        .Select(x => new FilterItem { TagName = x })
                        .Union((Types ?? new List<ClientModels.v1.LibItem.ItemType>()).Select(x => new FilterItem { TypeID = (int)x }))
                        .Union(new List<FilterItem> { new FilterItem { } });
                    lstFilters.EndRefresh();
                    actSpinner.IsVisible = false;
                }, UIThread);
                HasLoadedFilters = true;
            }
            else
            {
                lblViewing.Text = $"Viewing: {filter.Name}";
                lstFilters.IsVisible = false;
                cvLibItems.IsVisible = true;
                actSpinner.IsVisible = true;
                Task.Run(async () =>
                {
                    List<ClientModels.v1.LibItem> itms = (await API.v1a.Marketing.Async.List(filter.IsType ? new ClientModels.v1.LibItem.ItemType[] { (ClientModels.v1.LibItem.ItemType)filter.TypeID } : null)).ToList();
                    if (filter.IsTag)
                        itms = itms.Where(x => x.Tags.Contains(filter.TagName)).ToList();
                    return itms;
                }).ContinueWith(async (valtask) =>
                {
                    List<ClientModels.v1.LibItem> items = await valtask;
                    libItems = items.Select(x => new LibraryItem { Item = x }).ToList();
                    cvLibItems.ItemsSource = libItems;
                    lblViewing.IsVisible = true;
                    if (VIPMode)
                        RefreshVIPModeUI();
                    else
                        actSpinner.IsVisible = false;
                }, UIThread);
            }
            if (!VIPMode)
                using (Models.v1.Context db = DB.Context())
                    btnVIPModeEnter.TextColor = db.VIPCart.Any(x => x.UserID == Services.Common.UserID) ? Color.Blue : Color.Black;
        }

notice the extreme density in that, every line of code is milked to do as many things as I can get out of it.

[+] 1 user Likes phyrrus9's post
Reply

RE: C# - An introduction to time saving shortcuts #6
(07-28-2019, 10:59 PM)phyrrus9 Wrote:
(07-28-2019, 10:55 PM)Malcom Wrote: Nice tutorial, I've currently ended my last year in college (i'm studying Cyber Security) and the languages I learned were C#, PHP, Powershell and Python.
But the C# they learned me looks way different than yours? Here's an example:

Code:
            Console.WriteLine("Which sentence do you want to convert to a PigLatin?");
            string s = Console.ReadLine();
            Console.Write("Your sentence: " + s + "\n");

            string[] array = s.Split(' ');

            for (int i = 0; i < array.Length; i++)
            {
                string FirstLetter = array[i].Substring(0, 1);
                if (FirstLetter == "a" || FirstLetter == "e" || FirstLetter == "o" || FirstLetter == "u" || FirstLetter == "i")
                {
                    string new_word = array[i] + "way";
                    Console.Write(new_word + " ");
                }
                else
                {

                    string new_word = array[i].Substring(1, array[i].Length - 1) + array[i].Substring(0, 1) + "ay";
                    Console.Write(new_word + " ");

                }

            }
            Console.ReadLine();

Not to be overly harsh, but if you studied cyber security and you didn't cover C, then you got robbed. On top of that, universities today don't teach their students to innovate, they just teach them to pass the tests and maintain the accreditation of the school so that it can continue making money. You'll get better at C# with time, and what you have looks like perfectly fine C# code, but it's not efficient or easy to read. It's a good starting point, you should focus your efforts on the following:

1. removing unnecessary lines of code
2. getting rid of adding things to strings
3. efficiency in both memory and CPU cycles
4. simplicity
5. error handling. IMO, if you write code that doesn't even need additional error checks (use C#'s built ins to your advantage), you're on the right path.
I live in Europe, in the first year we always get kind of the easy stuff, the second and third year will be focussing on other courses. I will put all the courses I will study in my 3 years below. (I left out all the business and economic courses)

Spoiler:
[Image: EuOEeTR.png]
As long as you are living, you will face problems. But you serve a God who solves problems.

Reply

RE: C# - An introduction to time saving shortcuts #7
(07-28-2019, 11:09 PM)Malcom Wrote:
(07-28-2019, 10:59 PM)phyrrus9 Wrote:
(07-28-2019, 10:55 PM)Malcom Wrote: Nice tutorial, I've currently ended my last year in college (i'm studying Cyber Security) and the languages I learned were C#, PHP, Powershell and Python.
But the C# they learned me looks way different than yours? Here's an example:

Code:
            Console.WriteLine("Which sentence do you want to convert to a PigLatin?");
            string s = Console.ReadLine();
            Console.Write("Your sentence: " + s + "\n");

            string[] array = s.Split(' ');

            for (int i = 0; i < array.Length; i++)
            {
                string FirstLetter = array[i].Substring(0, 1);
                if (FirstLetter == "a" || FirstLetter == "e" || FirstLetter == "o" || FirstLetter == "u" || FirstLetter == "i")
                {
                    string new_word = array[i] + "way";
                    Console.Write(new_word + " ");
                }
                else
                {

                    string new_word = array[i].Substring(1, array[i].Length - 1) + array[i].Substring(0, 1) + "ay";
                    Console.Write(new_word + " ");

                }

            }
            Console.ReadLine();

Not to be overly harsh, but if you studied cyber security and you didn't cover C, then you got robbed. On top of that, universities today don't teach their students to innovate, they just teach them to pass the tests and maintain the accreditation of the school so that it can continue making money. You'll get better at C# with time, and what you have looks like perfectly fine C# code, but it's not efficient or easy to read. It's a good starting point, you should focus your efforts on the following:

1. removing unnecessary lines of code
2. getting rid of adding things to strings
3. efficiency in both memory and CPU cycles
4. simplicity
5. error handling. IMO, if you write code that doesn't even need additional error checks (use C#'s built ins to your advantage), you're on the right path.
I live in Europe, in the first year we always get kind of the easy stuff, the second and third year will be focussing on other courses. I will put all the courses I will study in my 3 years below. (I left out all the business and economic courses)

Spoiler:
[Image: EuOEeTR.png]

my mistake, I was under the impression you had completed your degree

[+] 1 user Likes phyrrus9's post
Reply






Users browsing this thread: 1 Guest(s)