Topics on References of Values
Topics on References of Values
A Referent
Creating a Reference to a Variable
In our introduction to variables, we saw how to declare a variable using a primitive type. As a reminder, here is an example:
using static System.Console;
double side = 248.57;
WriteLine("Square Characteristics");
WriteLine("----------------------");
WriteLine("Side: {0}", side);
WriteLine("======================");
This would produce:
Square Characteristics
----------------------
Side: 248.57
======================
Press any key to close this window . . .
When you declare a variable in a program, the compiler reserves some space for that variable in the computer memory. The location of a variable in memory is referred to as its address. As is the case for objects, when you declare a variable of a primitive type, a portion of the computer memory is allocated for it. On the other hand, if you declare a variable using the new operator, you are letting the compiler know that when it comes time to use that variable, you will use a reference to that variable or object, not the value itself. You can make the same suggestion to the compiler about a value of a primitive type. This means that you can declare a variable using a value type (int, double, etc), but let the compiler know that you will use a reference to that variable.
To use a reference to an existing variable, declare another variable of the same type as the original variable. The data type of the new variable declaration must be preceded by the ref keyword. Here is an example:
double side = 248.57;
ref double oneOf4Sides;
To indicate the variable to which you want to refer, you must assign its name to the new ref variable. You must precede the assigned variable with the ref keyword. This can be done as follows:
double side = 248.57;
ref double oneOf4Sides = ref side;
The original variable is called a referent.
Practical Learning: Introducing Parameters
using static System.Console;
PreparePayroll();
// -------------------------------------------------------
string GetFirstName()
{
WriteLine("FUN DEPARTMENT STORE");
WriteLine("=======================================================");
WriteLine("Payroll Preparation");
WriteLine("-------------------------------------------------------");
WriteLine("Enter the following pieces of information");
WriteLine("-------------------------------------------------------");
WriteLine("Employee Information");
WriteLine("-------------------------------------------------------");
Write("First Name: ");
string result = ReadLine()!;
return result;
}
string GetLastName()
{
Write("Last Name: ");
string result = ReadLine()!;
return result;
}
double GetBaseRate()
{
Write("Hourly Salary: ");
double wages = double.Parse(ReadLine()!);
return wages;
}
double GetMondayTimeWorked()
{
WriteLine("-------------------------------------------------------");
WriteLine("Time worked");
WriteLine("-------------------------------------------------------");
Write("Monday: ");
double time = double.Parse(ReadLine()!);
return time;
}
double GetTuesdayTimeWorked()
{
Write("Tuesday: ");
double time = double.Parse(ReadLine()!);
return time;
}
double GetWednesdayTimeWorked()
{
Write("Wednesday: ");
double time = double.Parse(ReadLine()!);
return time;
}
double GetThursdayTimeWorked()
{
Write("Thursday: ");
double time = double.Parse(ReadLine()!);
return time;
}
double GetFridayTimeWorked()
{
Write("Friday: ");
double time = double.Parse(ReadLine()!);
return time;
}
double Add2(double m, double n)
{
return m + n;
}
double Add5(double a, double b, double c, double d, double e)
{
return a + b + c + d + e;
}Using a Referenced Variable
After assigning the original variable (the referent) to the referenced variable, both the original variable and the referenced variable hold the same value. This is illustrated in the following code:
using static System.Console;
double side = 248.57;
ref double oneOf4Sides = ref side;
WriteLine("Square Characteristics");
WriteLine("------------------------");
WriteLine("Original Side: {0}", side);
WriteLine("Referenced Side: {0}", oneOf4Sides);
WriteLine("========================");
This would produce:
Square Characteristics
------------------------
Original Side: 248.57
Referenced Side: 248.57
========================
Press any key to close this window . . .
In the same way, you can declare as many referenced variables as you want and assign a previously declared referenced variable to each. All those referenced variables would hold the value of their referent. This can be illustrated as follows:
using static System.Console;
double side = 248.57;
ref double oneOf4Sides = ref side;
ref double siding = ref side;
ref double coast = ref side;
WriteLine("Square Characteristics");
WriteLine("------------------------");
WriteLine("Original Side: {0}", side);
WriteLine("Referenced Side: {0}", oneOf4Sides);
WriteLine("Referenced Side: {0}", siding);
WriteLine("Referenced Side: {0}", coast);
WriteLine("========================");
This would produce:
Square Characteristics
------------------------
Original Side: 248.57
Referenced Side: 248.57
Referenced Side: 248.57
Referenced Side: 248.57
========================
Press any key to close this window . . .
Updating a Referenced Variable
When you have declared a referenced variable and initialized it with a regular variable, both the original variable and the referenced variable would hold the same value. As a result, if you change the value of the regular variable, the referenced variable would hold the same value. This can be illustrated in the following code:
using static System.Console; double number = 927_495.862; ref double refNumber = ref number; WriteLine("Numeric Values"); WriteLine("----------------------------"); WriteLine("Original Value: {0}", number); WriteLine("Referenced Value: {0}", refNumber); WriteLine("============================"); number = 47_528.59; WriteLine("Numeric Values"); WriteLine("----------------------------"); WriteLine("Original Value: {0}", number); WriteLine("Referenced Value: {0}", refNumber); WriteLine("============================");
This would produce:
Numeric Values ---------------------------- Original Value: 927495.862 Referenced Value: 927495.862 ============================ Numeric Values ---------------------------- Original Value: 47528.59 Referenced Value: 47528.59 ============================ Press any key to close this window . . .
Referent with Functions and Methods
Passing a Referenced Variable to a Function
You already know that you can create a function that takes an argument by reference. When calling a function that takes an argument by reference, if you have a referenced variable, you can pass that variable as argument. You pass the argument as we saw about passing an argument by reference. This means that, when creating the function, in its parentheses, precede the data type of the parameter with the ref keyword. This can be done as follows:
using static System.Console;
void Show(ref double refNbr)
{
WriteLine("Numeric Values");
WriteLine("----------------------------");
WriteLine("Original Value: {0}", number);
WriteLine("Referenced Value: {0}", refNbr);
WriteLine("============================");
}
When calling the function, precede the name of the argument with the ref keyword. This can be done as follows:
using static System.Console; double number = 927_495.862; ref double refNumber = ref number; Show(ref refNumber); number = 47_528.59; Show(ref refNumber); void Show(ref double refNbr) { WriteLine("Numeric Values"); WriteLine("----------------------------"); WriteLine("Original Value: {0}", number); WriteLine("Referenced Value: {0}", refNbr); WriteLine("============================"); }
This would produce the same result we saw above.
Returning a Reference from a Function
In the previous lesson, we saw that you can create a function that uses one or more parameters created as references. Here is an example:
using static System.Console;
double mon, tue, wed, thu, fri;
void GetTimeWorked(ref double total)
{
WriteLine("Type the time worked for each day");
WriteLine("---------------------------------");
Write("Monday: ");
mon = double.Parse(ReadLine()!);
Write("Tuesday: ");
tue = double.Parse(ReadLine()!);
Write("Wednesday: ");
wed = double.Parse(ReadLine()!);
Write("Thursday: ");
thu = double.Parse(ReadLine()!);
Write("Friday: ");
fri = double.Parse(ReadLine()!);
total = mon + tue + wed + thu + fri;
}
double total = 0.00;
GetTimeWorked(ref total);
WriteLine("=================================");
WriteLine("Fun Department Store");
WriteLine("---------------------------------");
WriteLine("Time Worked");
WriteLine("=================================");
WriteLine($"Monday: {mon:f}");
WriteLine($"Tuesday: {tue:f}");
WriteLine("Wednesday: {0:f}", wed);
WriteLine($"Thursday: {thu:f}");
WriteLine("Friday: {0:F}", fri);
WriteLine("---------------------------------");
WriteLine("Total: {0:F}", total);
WriteLine("=================================");
Here is an example of running the program:
Type the time worked for each day --------------------------------- Monday: 8.5 Tuesday: 9 Wednesday: 10.5 Thursday: 9.5 Friday: 8 ================================= Fun Department Store --------------------------------- Time Worked ================================= Monday: 8.50 Tuesday: 9.00 Wednesday: 10.50 Thursday: 9.50 Friday: 8.00 --------------------------------- Total: 45.50 ================================= Press any key to close this window . . .
Notice that the function returns void. The C# language provides a way for you to return a reference (this is a feature available in some other languages such as C++). In other words, you can create a function that returns a reference. To proceed, when creating the function, specify its return scheme with the ref keyword and a data type of your choice, not void. Here is an example:
ref double GetTimeWorked()
{
. . .
}
The function must return a reference. As one way to make it happen, you can pass a reference parameter to the function, and then make the function return that parameter. This can be done as follows:
using static System.Console; double mon, tue, wed, thu, fri; ref double GetTimeWorked(ref double total) { WriteLine("Type the time worked for each day"); WriteLine("---------------------------------"); Write("Monday: "); mon = double.Parse(ReadLine()!); Write("Tuesday: "); tue = double.Parse(ReadLine()!); Write("Wednesday: "); wed = double.Parse(ReadLine()!); Write("Thursday: "); thu = double.Parse(ReadLine()!); Write("Friday: "); fri = double.Parse(ReadLine()!); total = mon + tue + wed + thu + fri; return ref total; } double total = 0.00; GetTimeWorked(ref total); WriteLine("================================="); WriteLine("Fun Department Store"); WriteLine("Time Worked"); WriteLine("================================="); WriteLine($"Monday: {mon:f}"); WriteLine($"Tuesday: {tue:f}"); WriteLine("Wednesday: {0:f}", wed); WriteLine($"Thursday: {thu:f}"); WriteLine("Friday: {0:F}", fri); WriteLine("---------------------------------"); WriteLine("Total: {0:F}", total); WriteLine("=================================");
When a Method of a Class or Record Returns a Reference
A methof of a class or that of a record can be made to return a referenced value. To make this happen, when creating the method, precede its return type with the ref keyword. This can be done as follows:
public class Number
{
public ref double GetValue()
{
return ...;
}
}
Such a method must return a reference variable. As one way you can make it happen, in the body of the method, you can declare a variable using a data type that is the same type specified for the method. The variable must be preceded with the ref keyword. At the end of the method, you can return that variable. To do this, the returned value must be preceded with the ref keyword. This can be done as follows:
public class Number
{
public ref double GetValue()
{
// A variable that is the same type as the return type of the method
ref double val ...;
// Returning the referenced variable
return ref val;
}
}
As we saw in our introduction to referents, whenever you declare a referenced variable, you must initialize it. When it comes to a method of a class, to address this issue, you can create a field that is the same type as the return type of the method. Then, in the body of the method, you can assign that field to the local variable. This can be done as follows:
public class Number
{
private double nbr;
public ref double GetValue()
{
ref double val = ref nbr;
return ref val;
}
}
After creating the class, you can use it. Of course, you must first declare an instance of it. From that variable, you can call the method that was created. Since you are calling a method that returns a referenced variable, to make sure you can access the right value, you should set the desired value of the variable after calling the method. Consider the following example:
using static System.Console; double number = 0d; ref double refNumber = ref number; Number nbr = new Number(); number = nbr.GetValue(); WriteLine("============================"); WriteLine("Numeric Values"); WriteLine("----------------------------"); WriteLine("Original Value: {0}", number); WriteLine("Referenced Value: {0}", refNumber); WriteLine("============================"); number = 286.82; WriteLine("Numeric Values"); WriteLine("----------------------------"); WriteLine("Original Value: {0}", number); WriteLine("Referenced Value: {0}", refNumber); WriteLine("============================"); public class Number { private double nbr; public ref double GetValue() { ref double val = ref nbr; return ref val; } }
This would produce::
============================ Numeric Values ---------------------------- Original Value: 0 Referenced Value: 0 ============================ Numeric Values ---------------------------- Original Value: 286.82 Referenced Value: 286.82 ============================ Press any key to close this window . . .
Referenced Tuples
Passing a Tuple by Reference
As seen with other types, you can create and use a reference of a tuple. To proceed, you can first create a tuple of your choice. Here is an example:
using static System.Console;
(int nbr, string fn, string ln, double sal) staff = (493_724, "Annette", "Wald", 44_444);
WriteLine("Staff Member");
WriteLine("------------------------");
Write("Employee #: ");
WriteLine(staff.nbr);
Write("First Name: ");
WriteLine(staff.fn);
Write("Last Name: ");
WriteLine(staff.ln);
Write("Yearly Salary: ");
WriteLine(staff.sal);
WriteLine("========================");
This would produce:
Staff Member ------------------------ Employee #: 493724 First Name: Annette Last Name: Wald Yearly Salary: 44444 ======================== Press any key to close this window . . .
To create a reference of a tuple, declare a new variable that has the same types and order of items. Start the new variable with the ref keyword and assign the original variable to the new one. The variable you are assigning must also start with the ref keyword. From that time, both the original and the new variables would have the same value. This can be verified as follows:
using static System.Console;
(int nbr, string fn, string ln, double sal) staff = (493_724, "Annette", "Wald", 44_444);
ref (int emplNumber, string firstName, string lastName, double salary) employee = ref staff;
WriteLine("Staff Member");
WriteLine("------------------------");
Write("Employee #: ");
WriteLine(staff.nbr);
Write("First Name: ");
WriteLine(staff.fn);
Write("Last Name: ");
WriteLine(staff.ln);
Write("Yearly Salary: ");
WriteLine(staff.sal);
WriteLine("========================");
WriteLine("Employee Record");
WriteLine("------------------------");
Write("Employee #: ");
WriteLine(employee.emplNumber);
Write("First Name: ");
WriteLine(employee.firstName);
Write("Last Name: ");
WriteLine(employee.lastName);
Write("Yearly Salary: ");
WriteLine(employee.salary);
WriteLine("========================");
This would produce:
Staff Member ------------------------ Employee #: 493724 First Name: Annette Last Name: Wald Yearly Salary: 44444 ======================== Employee Record ------------------------ Employee #: 493724 First Name: Annette Last Name: Wald Yearly Salary: 44444 ======================== Press any key to close this window . . .
After creating a referenced tuple, you can change the value of an item of either the original or the referenced variable. The changed value on the item would apply to the same item on the original or the referenced tuple. Consider the following example:
using static System.Console;
(int nbr, string fn, string ln, double sal) staff = (493_724, "Annette", "Wald", 44_444);
ref (int emplNumber, string firstName, string lastName, double salary) employee = ref staff;
WriteLine("Staff Member");
WriteLine("-----------------------------------------------------------");
Write("Employee #: ");
WriteLine(staff.nbr);
Write("First Name: ");
WriteLine(staff.fn);
Write("Last Name: ");
WriteLine(staff.ln);
Write("Yearly Salary: ");
WriteLine(staff.sal);
WriteLine("===========================================================");
WriteLine("Employee Record");
WriteLine("-----------------------------------------------------------");
Write("Employee #: ");
WriteLine(employee.emplNumber);
Write("First Name: ");
WriteLine(employee.firstName);
Write("Last Name: ");
WriteLine(employee.lastName);
Write("Yearly Salary: ");
WriteLine(employee.salary);
WriteLine("===========================================================");
// Updating a value on the original tuple
staff.fn = "George";
// Updating a value on the referenced tuple
employee.salary = 77_777;
WriteLine("After changing a value on other original or the reference...");
WriteLine("Staff Member");
WriteLine("-----------------------------------------------------------");
Write("Employee #: ");
WriteLine(staff.nbr);
Write("First Name: ");
WriteLine(staff.fn);
Write("Last Name: ");
WriteLine(staff.ln);
Write("Yearly Salary: ");
WriteLine(staff.sal);
WriteLine("===========================================================");
WriteLine("Employee Record");
WriteLine("-----------------------------------------------------------");
Write("Employee #: ");
WriteLine(employee.emplNumber);
Write("First Name: ");
WriteLine(employee.firstName);
Write("Last Name: ");
WriteLine(employee.lastName);
Write("Yearly Salary: ");
WriteLine(employee.salary);
WriteLine("===========================================================");
This would produce:
Staff Member ----------------------------------------------------------- Employee #: 493724 First Name: Annette Last Name: Wald Yearly Salary: 44444 =========================================================== Employee Record ----------------------------------------------------------- Employee #: 493724 First Name: Annette Last Name: Wald Yearly Salary: 44444 =========================================================== After changing a value on other original or the reference... Staff Member ----------------------------------------------------------- Employee #: 493724 First Name: George Last Name: Wald Yearly Salary: 77777 =========================================================== Employee Record ----------------------------------------------------------- Employee #: 493724 First Name: George Last Name: Wald Yearly Salary: 77777 =========================================================== Press any key to close this window . . .
Notice that, in the above example, a value of the tuple can be changed on the referenced tuple. In some cases, you may want to prevent the referenced tuple from changing the value of any of the item of the original tuple. We already know that, to put that restriction, you can apply the readonly keyword to the referenced tuple variable. Consider the following code:
(int nbr, string fn, string ln, double sal) staff = (493_724, "Annette", "Wald", 44_444);
ref readonly (int emplNumber, string firstName, string lastName, double salary) employee = ref staff;
staff.fn = "George";
employee.salary = 77_777;
This code would produce an error because the variable is read-only.
|
|
|||
| Previous | Copyright © 2011-2026, FunctionX | Friday 19 January 2024 | Next |
|
|
|||