Joining Operator: GroupJoin

The GroupJoin operator performs the same task as Join operator except that GroupJoin returns a result in group based on specified group key. The GroupJoin operator joins two sequences based on key and groups the result by matching key and then returns the collection of grouped result and key.

GroupJoin requires same parameters as Join.

let’s understand GroupJoin using following Student and Standard class where Student class includes StandardID that matches with StandardID of Standard class.

public class Student{ 
    public int StudentID { get; set; }
    public string StudentName { get; set; }
    public int StandardID { get; set; }
}

public class Standard{ 
    public int StandardID { get; set; }
    public string StandardName { get; set; }
}

Consider the following GroupJoin query example.

IList<Student> studentList = new List<Student>() { 
    new Student() { StudentID = 1, StudentName = "John", StandardID =1 },
    new Student() { StudentID = 2, StudentName = "Moin", StandardID =1 },
    new Student() { StudentID = 3, StudentName = "Bill", StandardID =2 },
    new Student() { StudentID = 4, StudentName = "Ram",  StandardID =2 },
    new Student() { StudentID = 5, StudentName = "Ron" } 
};

IList<Standard> standardList = new List<Standard>() { 
    new Standard(){ StandardID = 1, StandardName="Standard 1"},
    new Standard(){ StandardID = 2, StandardName="Standard 2"},
    new Standard(){ StandardID = 3, StandardName="Standard 3"}
};

var groupJoin = standardList.GroupJoin(studentList,  //inner sequence
                                std => std.StandardID, //outerKeySelector 
                                s => s.StandardID,     //innerKeySelector
                                (std, studentsGroup) => new // resultSelector 
                                {
                                    Students = studentsGroup,
                                    StandarFulldName = std.StandardName
                                });

foreach (var item in groupJoin)
{ 
    Console.WriteLine(item.StandarFulldName );

    foreach(var stud in item.Students)
        Console.WriteLine(stud.StudentName);
}

Reference

https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.groupjoin?view=net-7.0

Action, Func and Expression

Most times you’re going to want Func or Action if all that needs to happen is to run some code. You need Expression when the code needs to be analyzed, serialized, or optimized before it is run. Expression is for thinking about code, Func/Action is for running it.

In C#, passing a function as a parameter to another method or function is a powerful feature that allows for increased flexibility and code reusability. This technique, often referred to as “higher-order functions” or “function pointers,” enables you to treat functions as first-class citizens in your code.

Using Action Delegate

The Action delegate is a predefined delegate type provided by C# that represents a method that does not return a value but can accept up to sixteen input parameters.

Define the function signature that matches the action delegate you want to use. The action delegate represents a method that does not return a value and can accept up to 16 input parameters. For example, if you have a function with two input parameters of type int and string, the signature would be Action.

Create a method that takes an action delegate as an argument to use this delegate. The parameter should have the same signature as the function you want to pass. Inside the method, you can invoke the passed action delegate and use it just like any other function.

Here’s an example that demonstrates how to pass a function using the action delegate:

 // Define the function signature that matches the Action delegate
        static internal void MyFunction(int param1, string param2)
        {
            Console.WriteLine($"Action delegate demo - Parameters: {param1}, {param2}");
        }

        // Create a method that accepts a Action delegate as a parameter

        static internal void ProcessAction(Action<int, string> action)

        {
            // Invoke the passed action
            action(10, "Hello");
        }

        static void Main()
        {
            //usage example
            ProcessAction(MyFunction);
        }

In this example, we have a MyFunction method that matches the signature of the Action<int, string> delegate, and it does not return a value and only accepts two parameters: an int and a string.

The ProcessAction method accepts an Action<int, string> delegate as a parameter. It invokes the passed function using the delegate by calling action(10, “Hello”).

In the Main() method, we demonstrate the usage by calling ProcessAction and passing MyFunction as the argument. This will invoke MyFunction inside ProcessAction and output the parameters passed to it.

Using Func Delegate

The Func delegate is another predefined delegate type in C# that represents a method that takes input parameters and returns a value.

So to use this delegate, define the function signature that matches the Func delegate you want to use. The Func delegate can handle functions with up to 16 input parameters and a return type as the last type parameter. For example, if you have a function with two input parameters of type int and string that returns a bool, the signature would be Func<int, string, bool>.

A method that takes a Func delegate as a parameter should then be created, and the parameter’s signature should match that of the function you intend to pass. Inside the method, you can invoke the passed Func delegate and use it just like any other function. Here’s an example that demonstrates how to pass a function using the Func delegate:

 // Define the function signature that matches the Func delegate
        static internal bool MyFunction(int param1, string param2)
        {
            Console.WriteLine($"Function delegate deom - Parameters: {param1}, {param2}");
            return true;
        }


        // Create a method that accepts a Function delegate as a parameter

        static internal void ProcessFunc(Func<int, string, bool> func)
        {
            // Invoke the passed func and get the result
            bool result = func(10, "Hello");
            // Process the result
            Console.WriteLine($"Result: {result}");
        }

        static void Main()
        {
            // Usage example
            ProcessFunc(MyFunction);
        }

In this example, we have a MyFunction method that matches the signature of the Func<int, string, bool> delegate. It receives two parameters—an int and a string—and outputs a bool.

The ProcessFunc method accepts a Func<int, string, bool> delegate as a parameter. It invokes the passed function using the delegate and stores the result in the result variable. Finally, it processes the result by printing it to the console.

Using Expression

An expression simply turns a delegate into a data about itself. So a => a + 1 becomes something like “On the left side there’s an int a. On the right side you add 1 to it.” That’s it. You can go home now. It’s obviously more structured than that, but that’s essentially all an expression tree really is–nothing to wrap your head around.

So, in other words, an Expression contains the meta-information about a certain delegate.

An expression tree is a data structure that represents some code. It isn’t compiled and executable code. If you want to execute the .NET code represented by an expression tree, you must convert it into executable IL instructions. Executing an expression tree may return a value, or it may just perform an action such as calling a method.

You would convert an expression into a delegate using the following code:

Expression<Func<int>> add = () => 1 + 2;
var func = add.Compile(); // Create Delegate
var answer = func(); // Invoke Delegate
Console.WriteLine(answer);

Reference

https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/expression-trees/expression-trees-execution

https://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct

https://www.daveaglick.com/posts/using-expression-trees-to-get-class-and-member-names

Fonts vs PNG transparent images

Fonts are letters, numbers, and symbols designed using specific typefaces. They can apply to various design elements such as logos, headings, and body text. On the other hand, PNG (Portable Network Graphics) transparent designs are images with transparent backgrounds that can be layered over other graphics or backgrounds.

The main difference between font vs PNG transparent designs is their application. Font use to create typographic designs, while PNG transparent designs  use for creating image-based designs with transparency.

Fonts are ideal for creating text-heavy designs, while PNG transparent designs are perfect for creating graphics with intricate details such as icons, logos, and illustrations.

Since fonts are letters, numbers and symbols so it is possible they can not be rendered in some UI components. The rendering experience is an empty space with alternate text only. For example;

<a class="foo" title="Delete" href="#" onclick="foo.display(33);CancelEvent(event);\">
	<i class="fa fa-trash\"></i> Trash
</a>

Plus and Minu are universal fonts recognized by almost all components.

<a class="foo" title="Delete" href="#" onclick="foo.display(33);CancelEvent(event);\">
	<i class="fa fa-add\"></i> Trash
</a>

If a component doesn’t support font then + and – symbol will be rendered without any styles.

In the world of modern web, icons have become an indelible and integral part of UI design. Read about Font and SVG (Scalable vector graphics) icons. majority of the web development community prefers to use SVG icons;

Read more about Fonts Vs SVG here

Read about how to use SVG images in CSS and HTML here

Cascading Dropdown List

Create three dropdown lists, inside an HTML form.

The second and third dropdown list will display different options, depending on the value selected in the parent dropdown list.

Add HTML;

<form name="form1" id="form1" action="/action_page.php">
  Subjects: <select name="subject" id="subject">
    <option value="" selected="selected">Select subject</option>
  </select>
  <br><br>
  Topics: <select name="topic" id="topic">
    <option value="" selected="selected">Please select subject first</option>
  </select>
  <br><br>
  Chapters: <select name="chapter" id="chapter">
    <option value="" selected="selected">Please select topic first</option>
  </select>
  <br><br>
  <input type="submit" value="Submit">
</form>

Add JavaScript;

var subjectObject = {
  "Front-end": {
    "HTML": ["Links", "Images", "Tables", "Lists"],
    "CSS": ["Borders", "Margins", "Backgrounds", "Float"],
    "JavaScript": ["Variables", "Operators", "Functions", "Conditions"]
  },
  "Back-end": {
    "PHP": ["Variables", "Strings", "Arrays"],
    "SQL": ["SELECT", "UPDATE", "DELETE"]
  }
}
window.onload = function() {
  var subjectSel = document.getElementById("subject");
  var topicSel = document.getElementById("topic");
  var chapterSel = document.getElementById("chapter");
  for (var x in subjectObject) {
    subjectSel.options[subjectSel.options.length] = new Option(x, x);
  }
  subjectSel.onchange = function() {
    //empty Chapters- and Topics- dropdowns
    chapterSel.length = 1;
    topicSel.length = 1;
    //display correct values
    for (var y in subjectObject[this.value]) {
      topicSel.options[topicSel.options.length] = new Option(y, y);
    }
  }
  topicSel.onchange = function() {
    //empty Chapters dropdown
    chapterSel.length = 1;
    //display correct values
    var z = subjectObject[subjectSel.value][this.value];
    for (var i = 0; i < z.length; i++) {
      chapterSel.options[chapterSel.options.length] = new Option(z[i], z[i]);
    }
  }
}

Reference

https://www.w3schools.com/howto/howto_js_cascading_dropdown.asp