C# 7 and .NET Core Cookbook
上QQ阅读APP看书,第一时间看更新

How to do it...

  1. Start off by creating a new class in the Program.cs file of your Visual Studio console application. You can call your class anything, but for the purposes of this book I will simply be calling my class Chapter1. Your code should now look as follows:
        namespace cookbook
{
class Program
{
static void Main(string[] args)
{

}
}

public class Chapter1
{

}
}
  1. This is the format we will be using throughout this chapter. Let's assume that we want to write a method that needs to calculate the average score for a variable number of students. No grade has the same number of students in each class. Therefore, we want our method to return the number of students in the class for the calculated average score. Change the static void main method to contain a list of scores. We are also creating a new instance of the Chapter1 class and calling the method GetAverageAndCount(), which will be used to return the two values we need.

I will be hardcoding this for illustration purposes; in reality, though these scores can be for any number of students. Be sure to add the values exactly as I have in the code listing as I will be illustrating a final gotcha at the end of this recipe.

        static void Main(string[] args)
{
int[] scores = { 17, 46, 39, 62, 81, 79, 52, 24 };
Chapter1 ch1 = new Chapter1();
var s = ch1.GetAverageAndCount(scores);
}
  1. It is here that we can use the power of Tuples to declare the GetAverageAndCount() method in the Chapter1 class. It accepts an array of integer scores and looks as follows:
        public (int, int) GetAverageAndCount(int[] scores)
{

}
  1. Pay close attention to the return Tuple type (int, int). We are only returning two values from the GetAverageAndCount() method, but in reality you can return several values if needed. In order to run your code sample, we will create a dummy implementation of this method. To do this, just include a Tuple literal that returns two zeros. 
        public (int, int) GetAverageAndCount(int[] scores)
{
var returnTuple = (0, 0);
return returnTuple;
}
  1. Go back to the static void Main method where the Tuple returning method is called and write code to consume the return values. Every Tuple you create will expose members called Item1, Item2, Item3, and so on. These are used to get the values returned from a Tuple returning method.
        static void Main(string[] args)
{
int[] scores = { 17, 46, 39, 62, 81, 79, 52, 24 };
Chapter1 ch1 = new Chapter1();
var s = ch1.GetAverageAndCount(scores);
WriteLine($"Average was {s.Item1} across {s.Item2} students");
ReadLine();
}
  1. Be sure to add the following using the directive before the namespace.
        using static System.Console;
  1. You will notice that we used s.Item1 and s.Item2 to reference the return values returned from our GetAverageAndCount() method. While this is totally legal, it isn't very descriptive and makes it difficult to infer the usage of the variable returned. It basically means that you would have to remember that Item1 is the average value and Item2 is the count value. Perhaps, it is the other way around? Is Item1 the count and Item2 the average? It really depends on what you are doing inside the GetAverageAndCount() method (which can change over time). Our Tuple returning method can therefore be enhanced as follows:
        public (int average, int studentCount) 
GetAverageAndCount(int[] scores)
{
var returnTuple = (0, 0);
return returnTuple;
}
  1. The Tuple return type can now declare variable names for its elements. This makes it easy for the caller of the GetAverageAndCount() method to know which value is which. You can still keep on using s.Item1 and s.Item2, but it is now much easier to change the calling code in the static void Main method accordingly:
        static void Main(string[] args)
{
int[] scores = { 17, 46, 39, 62, 81, 79, 52, 24 };
Chapter1 ch1 = new Chapter1();
var s = ch1.GetAverageAndCount(scores);
WriteLine($"Average was {s.average} across {
s.studentCount} students");
ReadLine();
}
  1. Changing the interpolated string in WriteLine, we see that the usage of the values returned by the Tuple is much clearer. You now know that the first value is the average and that the second value is the count of the students used to calculate the average. Tuples, however, allow developers more flexibility. Remember the Tuple literal in the GetAverageAndCount() method? We simply added this in the dummy implementation as follows:
        var returnTuple = (0, 0);
  1. C# 7.0 also allows developers to add names to Tuple literals. Inside the GetAverageAndCount() method, change your Tuple literal as follows:
        var returnTuple = (ave:0, sCount:0);
  1. I have just named the first value a name of ave (for average) and the second  sCount (for student count). This is some really exciting stuff! After you have modified your Tuple literal, your dummy implementation of the GetAverageAndCount() method should look as follows:
        public (int average, int studentCount) 
GetAverageAndCount(int[] scores)
{
var returnTuple = (ave:0, sCount:0);
return returnTuple;
}

Tuples play really nicely together. As long as the Tuple types match up, you do not have to worry that the ave and sCount names in the Tuple literal don't match the average and studentCount names of the return type.