Letting a Variable

Introduction

We saw that you can get the result of a LINQ statement from the select section. In reality, the select statement simply indicates that the result is ready and it hands it to the other parts of the program. Instead of getting the result directly from the select statement, you can first store it in a local LINQ variable. This allows you to treat the result as a variable that you can then manipulate before getting the final result.

Letting a Local Variable

To allow you to declare a local variable in the LINQ statement, the LINQ provides an operator named let. You must use it before the select statement to hold the result and you must initialize the variable. Normally, the variable can hold a constant value. At the end of the query, you can select that let variable and later use it as the returned value. Here is an example:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            var loan = new double[] { 1250d, 12.05d, 36d };

            var number = from n
                         in loan
                         let principal = 2465D
                         select principal;

            foreach (var nbr in number)
            {
                txtPrincipal.Text = nbr.ToString();
            }
        }
    }
}

This would produce:

Letting a Local Variable

Letting a Value from a List

If your query is based on an array, you can assign a value of that array to the let variable. You can get the value based on the index that represents its position in the array. Here is an example:

private void Exercise_Load(object sender, EventArgs e)
{
    var loan = new double[] { 1250d, 12.05d, 36d };

    var number = from n
                 in loan
                 let principal = loan[0]
                 select principal;

    foreach (var nbr in number)
    {
        txtPrincipal.Text = nbr.ToString();
    }
}

This would produce:

Letting a Local Variable

Letting an Expression

Instead of a constant value, you can create an expression and assign it to the let variable. The expression can be made of constant values. You can also use the members of the array by accessing each based on its index. Here is an example:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            var loan = new double[] { 800, 9, 4 }; // 1250d, 12.05d, 36d };

            // Amount Paid = Principal(1 + Interest Rate * Periods)
            //             = Principal{1 + [(Interest Rate / 100) * (Periods in Months / 12)]}
            var number = from n
                         in loan
                         let amtPaid = loan[0] * (1 + (loan[1] / 100 * loan[2]/12))
                         select amtPaid;

            foreach (var nbr in number)
            {
                txtAmountPaid.Text = nbr.ToString();
            }
        }
    }
}

This would produce:

Letting a Local Variable

Letting Many Values

You can declare more than one let variable. When you exit the statement, you can select only one of the variables and use it outside of the query. Here is an example:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            var loan = new double[] { 1250d, 12.05d, 36d };

            // Future Value  = Principal(1 + Interest Rate * Periods)
            //               = Principal{1 + [(Interest Rate / 100) * (Periods in Months / 12)]}
            // Interest Paid = Future Value - Principal
            var number = from n
                         in loan
                         let futurevalue = loan[0] * (1 + (loan[1] / 100 * loan[2] / 12))
                         let interestPaid = futurevalue - loan[0]
                         select interestPaid;

            foreach (var nbr in number)
            {
                txtInterestPaid.Text = nbr.ToString("F");
            }
        }
    }
}

This would produce:

Letting a Local Variable

You can include a where condition in your let variable if you want to check a condition. Here is an example:

private void Exercise_Load(object sender, EventArgs e)
{
    var loan = new double[] { 1250d, 12.05d, 36d };

    var number = from n
                 in loan
            	 where loan[0] > 1000
                 let futurevalue = loan[0] * (1 + (loan[1] / 100 * loan[2] / 12))
                 select futurevalue;

    foreach (var nbr in number)
    {
        txtFutureValue.Text = nbr.ToString("F");
    }
}

The where statement can be included before or after the let statement and you would get the same result:

private void Exercise_Load(object sender, EventArgs e)
{
    var loan = new double[] { 1250d, 12.05d, 36d };

    var number = from n
                 in loan
                 let futurevalue = loan[0] * (1 + (loan[1] / 100 * loan[2] / 12))
	         where loan[0] > 1000
                 select futurevalue;

    foreach (var nbr in number)
    {
        txtFutureValue.Text = nbr.ToString("F");
    }
}

Letting a Sub-List

In the LINQ, the let operator is used to declare a local variable in a query statement. To specify the value of the variable, you can create an expression that combines the members of a class and assign that expression to the let variable. To end your query, select that variable. Outside the query, access that variable from the var variable of the foreach loop. Here is an example:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            Video[] lstVideos = new Video[]
        {
            new Video(274880, "Platoon", "Oliver Stone", "R", 1986, false),
            new Video(792075, "Two for the Money", "D.J. Caruso", "R", 2008, true),
            new Video(283748, "Cousin Vinny (My)", "Jonathan Lynn", "R", 1992, false),
            new Video(593940, "Natural Born Killers", "Oliver Stone", "R", 1994, true),
            new Video(900245, "Her Alibi", "Bruce Beresford", "PG-13", 1998, false),
            new Video(773022, "Distinguished Gentleman (The)", "Jonathan Lynn", "R", 1992, false),
            new Video(961973, "Wall Street", "Oliver Stone", "R", 2000, false),
            new Video(180358, "Memoirs of a Geisha", "Rob Marshall", "PG-13", 2006, true)
        };

            var vdos = from videos
                       in lstVideos
                       let video = "\"" + videos.Title + "\" directed by " + videos.Director + ", released in " + videos.YearReleased.ToString()
                       select video;

            foreach (var vdo in vdos)
                cbxVideos.Items.Add(vdo);
        }
    }

    readonly record struct Video
    {
        public int    ShelfNumber  { get; init; }
        public string Title        { get; init; }
        public string Director     { get; init; }
        public string Rating       { get; init; }
        public int    YearReleased { get; init; }
        public bool   WideScreen   { get; init; }

        public Video(int id, string title, string dir, 
                     string rating, int year, bool hd = false)
        {
            ShelfNumber = id;
            Title = title;
            Director = dir;
            Rating = rating;
            YearReleased = year;
            WideScreen = hd;
        }
    }
}

This would produce:

Video Collection

If you need a condition, add a where statement before or after the let expression. Here is an example:

var vdos = from videos
           in lstVideos
           where videos.Director == "Oliver Stone"
           let video = "\"" + videos.Title + "\" directed by " + videos.Director + ", released in " + videos.YearReleased.ToString()
           select video;

Of course, you can order the list and/or use a conjunction or disjunction.

Letting New Values

Declaring a New local Variable

We mentioned that we could declare one or more let variables in a query but we could get only one of those variables out of the query. To let you get more that one variable outside of the query, the LINQ provides an operator name new. It must follow the select keyword in the following formula:

var SubListName = from ValueHolder
                   in List
                   select new
		  {
		  };

As you can see, to use the new operator, after the select keyword, type new followed by an opening and a closing curly brackets, "{" and "}" . Inside the brackets, declare any variable of your choice and assign it the value you want. The value can be any constant you want. Here is an example:

private void Exercise_Load(object sender, EventArgs e)
{
    var numbers = new double[] { 1250d, 12.05d, 36d };

    var number = from n
                 in numbers
                 select new
                 {
                     something = 6500
                 };
}

If you declare more than one variable, separate them with commas. Here are examples:

private void Exercise_Load(object sender, EventArgs e)
{
    var numbers = new double[] { 1250d, 12.05d, 36d };

    var number = from n
                 in numbers
                select new
                 {
                     something = 6500, another 4.006, more 5
                 };
}

Remember that you can declare each variable on its own line to make the code easier to read.

If you are using the values from an array, you can locate a value by its index and assign it to the desired local variable. Here are examples:

var number = from n
             in numbers
             select new
             {
                 Principal    = numbers[0],
                 InterestRate = numbers[1],
                 Periods      = numbers[2]
             };

Either way, to access a new variable outside the query, use a foreach loop to get a contextual variable. In the body of foreach, access each new variable using the period operator. Here are examples:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            var numbers = new double[] { 6500d, 11.65d, 48u };

            var number = from n
                         in numbers
                         select new
                         {
                             Principal = numbers[0],
                             InterestRate = numbers[1],
                             Periods = numbers[2]
                         };

            foreach (var member in number)
            {
                txtPrincipal.Text = member.Principal.ToString();
                txtInterestRate.Text = member.InterestRate.ToString();
                txtPeriods.Text = member.Periods.ToString();
            }
        }
    }
}

Instead of a constant or a member of an array, a new variable can be assigned an expression. The expression can be made of constants, the members of an array, or a combination of constants and members of the array. Here are examples:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            var numbers = new double[] { 6500d, 11.65d, 48u };

            var number = from n
                         in numbers
                         select new
                         {
                             Principal = numbers[0],
                             InterestRate = numbers[1],
                             Periods = numbers[2],
                             FutureValue = numbers[0] * (1 + (numbers[1] / 100 * numbers[2] / 12)),
                             InterestPaid = (numbers[0] * (1 + (numbers[1] / 100 * numbers[2] / 12))) - numbers[0],
                         };

            foreach (var member in number)
            {
                txtPrincipal.Text = member.Principal.ToString();
                txtInterestRate.Text = member.InterestRate.ToString();
                txtPeriods.Text = member.Periods.ToString();
                txtFutureValue.Text = member.FutureValue.ToString("F");
                txtInterestPaid.Text = member.InterestPaid.ToString("F");
            }
        }
    }
}

This would produce:

New Local Variables

If necessary, you can include a where statement to check a condition. The where statement must be written before the select new section. Here is ab example:

private void Exercise_Load(object sender, EventArgs e)
{
    var numbers = new double[] { 6500d, 11.65d, 48u };

    var number = from n
                 in numbers
                 where numbers[0] > 5000
                 select new
                 {
                     Principal    = numbers[0],
                     InterestRate = numbers[1],
                     Periods      = numbers[2],
                     Futurevalue  = numbers[0] * (1 + (numbers[1] / 100 * numbers[2] / 12)),
                     InterestPaid = (numbers[0] * (1 + (numbers[1] / 100 * numbers[2] / 12))) - numbers[0]
                 };

    foreach (var member in number)
    {
        txtPrincipal.Text = member.Principal.ToString();
        txtInterestRate.Text = member.InterestRate.ToString();
        txtPeriods.Text = member.Periods.ToString();
        txtFutureValue.Text = member.Futurevalue.ToString("F");
        txtInterestPaid.Text = member.InterestPaid.ToString("F");
    }
}

Creating a New Class

As we have seen above, if you query a list whose records are based on a class, you can access the members (properties and methods) of the class both in the query and in the foreach loop. As an alternative, the LINQ allows you to declare various variables in the query and access those variables in the foreach loop. To declare such variables, start with select new followed by "{" and "}":

var SubListName = from ValueHolder
		  in List
                  select new
		  {
		          ValueHolder.ClassMember1  = Value1
                      ValueHolder.ClassMember1  = Value2
                      ValueHolder.ClassMember_n = Value_n
		  };

Inside the curly brackets, declare each variable and assign it the desired value. The value can be a member of the class. Here is an example:

var vdos = from videos
           in lstVideos
           select new
           {
               ReferenceCode = videos.ShelfNumber
           };

Actually, the variable can hold the same name as a member of the class. In the same way, you can declare as many variables as you want and assign the desired class members to them. Separate the declarations with commas. Outside the query, to access a new variable, qualify it with a period operator applied to the foreach variable. Here are examples:

var vdos = from videos
           in lstVideos
           select new
           {
               ReferenceCode = videos.ShelfNumber,
               Name = videos.Title,
               Director = videos.Director,
               Viewership = videos.Rating,
               CopyrightYear = videos.YearReleased,
               WideScreen = videos.WideScreen,
           };

foreach (var vdo in vdos)
{
    ListViewItem lviCollection = new ListViewItem(vdo.ReferenceCode.ToString());

    lviCollection.SubItems.Add(vdo.Name);
    lviCollection.SubItems.Add(vdo.Director);
    lviCollection.SubItems.Add(vdo.Viewership);
    lviCollection.SubItems.Add(vdo.CopyrightYear.ToString());
    lviCollection.SubItems.Add(vdo.WideScreen.ToString());
    lvwCollection.Items.Add(lviCollection);
}

This would produce:

Video Collection

Instead of one value, the value of a new variable can be an expression that is a combination of values (constants and/or class members). Here are examples:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            Video[] lstVideos = new Video[]
        {
            new Video(274880, "Platoon", "Oliver Stone", "R", 1986, false),
            new Video(792075, "Two for the Money", "D.J. Caruso", "R", 2008, true),
            new Video(283748, "Cousin Vinny (My)", "Jonathan Lynn", "R", 1992, false),
            new Video(593940, "Natural Born Killers", "Oliver Stone", "R", 1994, true),
            new Video(900245, "Her Alibi", "Bruce Beresford", "PG-13", 1998, false),
            new Video(773022, "Distinguished Gentleman (The)", "Jonathan Lynn", "R", 1992, false),
            new Video(961973, "Wall Street", "Oliver Stone", "R", 2000, false),
            new Video(180358, "Memoirs of a Geisha", "Rob Marshall", "PG-13", 2006, true)
        };

            var vdos = from videos
                       in lstVideos
                       select new
                       {
                           ReferenceCode = videos.ShelfNumber,
                           Description = videos.Title + " (" + videos.YearReleased + ") directed by " + videos.Director,
                           Rating = videos.Rating,
                           WideScreen = videos.WideScreen,
                       };

            foreach (var vdo in vdos)
            {
                ListViewItem lviVideo = new ListViewItem(vdo.ReferenceCode.ToString());

                lviVideo.SubItems.Add(vdo.Description);
                lviVideo.SubItems.Add(vdo.Rating.ToString());
                lviVideo.SubItems.Add(vdo.WideScreen.ToString());
                lvwVideos.Items.Add(lviVideo);
            }
        }
    }

    readonly record struct Video
    {
        internal int    ShelfNumber  { get; init; }
        internal string Title        { get; init; }
        internal string Director     { get; init; }
        internal string Rating       { get; init; }
        internal int    YearReleased { get; init; }
        internal bool   WideScreen   { get; init; }

        public Video(int id, string title, string dir, 
                     string rating, int year, bool hd = false)
        {
            ShelfNumber = id;
            Title = title;
            Director = dir;
            Rating = rating;
            YearReleased = year;
            WideScreen = hd;
        }
    }
}

This would produce:

Video Collection


Previous Copyright © 2008-2023, FunctionX, Inc. Wednesday 15 September 2021 Next