Pages

Sunday, April 24, 2022

c# async/await

 Async/Await for c#. 

Two benefits:

  • UI is not locked up because control is returned to the calling method.
  • If the async calls do not depend on each other, then they can be run in parallel.

Parallel example:

Use a foreach and add Task to a List of Tasks. 

var tasks = new List<Task<string>>();

foreach (string site in listOfWebsites)
{
    tasks.Add(Task.Run( () => DownloadWebsite(site)));
}

var results = await Task.WhenAll(tasks);

Thursday, December 31, 2020

c# Delegates

Delegates are methods that are passed in as a parameter. Now, you can change the implementation of the method that is passed in from a different part of the code. For instance, "mentionSubTotal" can be implemented differently (discount is applied differently) from another location. 

Delegates are pointers to functions. But what is the purpose of calling functions indirectly (passing them in) via delegates versus calling that same function directly? 

Delegates are used to communicate between two parties. The main use of delegates are callbacks, callbacks, callbacks ...  

public class ShoppingCartModel

    {

        public delegate void MentionDiscount(decimal subTotal);

        public List<ProductModel> Items { get; set; } = new List<ProductModel>();

        

        // These are the 3 types of delegates.

        // 1) MentionDiscount is the "raw" delegate

        // 2) Func takes params (up to 16) and returns a value. No out params allowed.

        // 3) Action takes params (up to 15) and returns void. 


// Here is example using all 3 forms. Generally, you would only use one delegate, not 3). 

        public decimal GenerateTotal(MentionDiscount mentionSubtotal,

            Func<List<ProductModel>, decimal, decimal> calculateDiscountedTotal,

            Action<string> tellUserWeAreDiscounting)

        {

            decimal subTotal = Items.Sum(x => x.Price);


            mentionSubtotal(subTotal);


            tellUserWeAreDiscounting("We are applying your discount.");


            return calculateDiscountedTotal(Items, subTotal);  // returns decimal

        }

    }


From the calling method side, there are 2 ways to do.

1) You can create the method and pass in the method name:

Console.WriteLine($"Shopping cart subtotal: {cart.GenerateTotal(SubTotalAlert, CalculateLeveledDiscount, AlertUser):C2}");

All 3 methods will be defined in the class. For example, SubTotalAlert is defined here and passed as a parameter above.

private static void SubTotalAlert(decimal subTotal)

        {

            Console.WriteLine($"The subtotal is {subTotal:C2}");

        }


2) Instead of defining methods, you can write anonymous functions inline. All 3 methods are written as inline parameters and passed as parameters. 

decimal total = cart.GenerateTotal((subTotal) => Console.WriteLine($"The subtotal for cart 2 is {subTotal:C2}"),

                (products, subTotal) => {

                    if(products.Count > 3)

                    {

                        return subTotal * 0.5M;

                    }

                    else

                    {

                        return subTotal;

                    }

                },

                (message) => Console.WriteLine($"Cart 2 Alert: { message }"));

Wednesday, December 30, 2020

c# events

1) Create the event in Customer class. The <TYPE> can be string, decimal, bool, class, etc. 

public event EventHandler<decimal> OverdraftEvent; 


2) Place code to trigger the event.

public void MakePayment (decimal amount)

    if (amount < accountFunds)   // Not enough. Create event trigger. 

           OverdraftEvent?.Invoke(this, amount);

}


3) Create listeners for the event. Attached methods to run when event is triggered. You can place the event listeners in different classes/places as needed. 

private void WireUpForm()

{

    customer.Checking.OverdraftEvent += CheckingAccount_OverdraftEvent;

}


4) Create method that is run when event is triggered. 

private void CheckingAccount_OverdraftEvent(object sender, decimal e)

{

    // do something to handle event ... for example:

    errorMessage.Text = $"Not enough funds available for your {string.Format("{0:C2}", e)} transaction";

}


5) Remove listeners when app is closing. Else, the app may not fully close and get stuck in memory with no garbage collect. This leads to memory leaks !

customer.Checking.OverdraftEvent -= CheckingAccount_OverdraftEvent;

Friday, August 14, 2020

Rebase steps

 Terminal > 

git rebase -i HEAD~3

> GIT window comes up to make changes

[[[ > If I want to cancel, without changes, use # to comment out all lines and "wq!". No changes will be made.

> OR another way is to use "q!" to quit. Then use "git rebase --abort". ]]]

replace "pick" with s or f

ESC > : > wq! > press ENTER

git push -f origin feature/test-9999_sampleBranch    (force push will completely overwrite the origin branch)

Thursday, September 5, 2019

Resolve merge conflicts

SourceTree > rebase branch on top of Develop > Merge Conflicts !


Go to Visual Studio > Team Explorer > Changes > Conflicts

Click each conflict and click MERGE button.
Resolve (left side) by adding both changes.
Click "Accept Merge" top left.


Conflicts are resolved.


Go to SourceTree. Will not be on a branch. Stage all changes.
> Terminal > git rebase --continue






This will finish rebase and go to correct branch. If all looks good, then do a final push:
> Terminal > git push -f origin feature/3100_NewFeatureBranch

Saturday, January 12, 2019

React JS notes

- ES7 to generate quick template

In VS Code, go to 1) Extensions tab  2) Install ES7



This makes creating new JS files easy.

Create new file:  TestFile.js
Type "rce" and press Tab (rcf for function template)
It auto creates this template code:




- UUID (unique id generator)

> CNTL - C to stop dev server
> npm i uuid  (to install package)
> npm start (restart dev server)

import uuid from 'uuid';

id: uuid.v4();   < this will generate the ID


- React Router

> npm i react-router-dom


- HTTP API library (Axios) - can use instead of jQuery or fetch

> npm i axios





Saturday, December 22, 2018

SOLID - Liskov Substitution Principle

If S is a subtype of T, then objects of type T can be substituted by objects of type S without breaking the program.

public class Employee {
    public string Firstname {get; set;}
    public string Lastname { get; set;}

    public virtual void AssignManager (Employee Manager)
    {
          // set manager for employee
    }
}


Employee emp = new Employee();
emp.AssignManager();


Above, Employee type is T.


public class Staff : Employee {
    public string Dept {get; set;}
    public string Manager {get; set;}
}

Above, Staff (S) is a subtype of T (Employee). Liskov says that since S is a subtype of T, then this should work:


Employee emp = new Staff();
emp.AssignManager();


Let's create another subtype of Employee (T).

public class CEO : Employee{
       public string Rating {get; set;}
       public override void AssignManager(Employee manager)
       {
               throw new Exception("CEO does not have a manager");
       }
}


Above, CEO is subtype of Employee. However, this does not work and thus, it violates the Liskov Principle:

Employee emp = new CEO();
emp.AssignManager();

This code throws an exception because 1) CEO does not have a manager  2) code is set to throw error for invalid method.

Liskov Sub Principle states that Staff() should be a TRUE Employee().
CEO should be a TRUE Employee(), but it is not. So LSP is violated.

How to fix so that even CEO (subtype object of T) can be substituted for the objects of T? So that above code works?