(C# Language) Practice Exercise on Property changed event and Lambdas

Create a class called MyNumber with a property called Number of Int32 type. This class should contain an event delegate that takes one argument of Int32 type. The class MyNumber should raise this event when the Number property changes. The changed value should be sent as an argument to all delegates that register to this event. Inside Main create an object of MyNumber and attach an event handler that prints the changed value. The event handler should be an anonymous expression lambda that receives an Int32 argument and prints the number to console. Test the project by changing the Number property. If you did the things correctly, then you should see the event handler called. This might be a difficult one. So please go through the solution if you find the question itself difficult to understand.
(Rev. 19-Mar-2024)

Categories | About |     |  

Parveen,

Objectives of this Exercise

This exercise introduces you to

  1. Property syntax
  2. Raising events
  3. Expression lambdas as event handlers

Video Explanation (see it happen!)

Please watch the following youtube video:

The Solution

Create a C# .NET Core console project as usual. Add a class called MyNumber. You can obtain the completed project from the downloads attached to this video. Now I will discuss the class.

First we have to add an event delegate that accepts one Int32 type of argument and returns void. We have already learnt that dotnet core provides a built-in Action<T> delegate that accepts one argument and returns a void. So we can define a public event called, let's say, public event Action? NumberChanged;

An Action delegate is usually not used for event handlers.

It is more appropriate to use built-in delegates like EventHandler. These delegates contain a parameter to contain the sender of the event. The EventHandler<T> delegate is different from an Action<T> delegate only in the sender parameter void EventHandler<TEventArgs>(object? sender, TEventArgs e);

So let's add a data member for the event delegate and call it NumberChanged.

The event keyword signifies that it is a multicast delegate. Many multiple subscribers can subscribe to this delegate. All delegates will be notified when the event is raised. We will be later adding a subscriber in the Main function.


// mynumber.cs 

// project is in the attached downloads 

internal class MyNumber
{
  public event EventHandler<Int32>? NumberChanged;

  private Int32 _number;

  public Int32 Number
  {
    get => _number;

    set
    {
      if (_number != value)
      {
        _number = value;

        // ?. null conditional operator 
        // is a safety guard. Invoke is not 
        // called if NumberChanged is null 
        NumberChanged?.Invoke(this, _number);
      }
    }
  }
}

Next we add a backing member for the Number property.

The getter for the property returns _number.

The setter for the property sets _number = value, if there is a change.

The event is raised by a call to Invoke. The first argument is sender and the second the new number. The question mark after NumberChanged? means that Invoke will not be called if NumberChanged is null, which happens if there is no subscriber for this event.

Main in Program.cs

Next open the Program.cs file. Let's study the Main function now!

First of all we have created an object of the MyNumber class.


// program.cs file 

MyNumber mn = new();

// attach anonymous function 
// using expression lambda 
mn.NumberChanged += (s, n) => Console.WriteLine($"num = {n}");

Console.Write("Enter number: ");

mn.Number = Int32.Parse(Console.ReadLine() ?? "0");

The NumberChanged event is subscribed by using the += operator. The handler is an expression lambda. The first argument s is the sender and the second n is the changed value. This function gets called when the NumberChanged event is raised by the MyNumber class.

Run the Project

We can now run the project. It asks to enter a number. When a number is entered it prints the new value through the attached event handler.

Another Example

Study this class.


internal class MyNumber
{
  public event PropertyChangedEventHandler? PropertyChanged;

  private UInt32 _number;

  private UInt16 _lowPart;

  private UInt16 _highPart;

  private static UInt32 makeUInt32(UInt16 l, UInt16 h)
  {
    byte[] lowBytes = BitConverter.GetBytes(l);
    byte[] highBytes = BitConverter.GetBytes(h);

    byte[] numBytes = lowBytes.Concat(highBytes).ToArray();

    return BitConverter.ToUInt32(numBytes, 0);
  }

  public UInt16 LowPart
  {
    get => _lowPart;
    set
    {
      if (_lowPart != value)
      {
        Number = makeUInt32(value, _highPart);
      }
    }
  }

  public UInt16 HighPart
  {
    get => _highPart;

    set
    {
      if (_highPart != value)
      {
        Number = makeUInt32(_lowPart, value);
      }
    }
  }

  public UInt32 Number
  {
    get => _number;

    set
    {
      if (_number != value)
      {
        _number = value;

        byte[] numBytes = BitConverter.GetBytes(_number);

        _lowPart = BitConverter.ToUInt16(numBytes, 0);

        _highPart = BitConverter.ToUInt16(numBytes, 2);

        PropertyChanged?.Invoke(this, 
          new PropertyChangedEventArgs("Number Changed!"));
      }
    }
  }
}

This is the main function.


// program.cs 

MyNumber mn = new();

Console.Write("Enter number: ");

mn.Number = UInt32.Parse(
              Console.ReadLine() ?? "0");


This Blog Post/Article "(C# Language) Practice Exercise on Property changed event and Lambdas" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.