• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

C# 8.0和.NET Core 3.0高级编程 分享笔记四:第一部分编写函数

开发技术 开发技术 5小时前 1次浏览

本章介绍如何编写函数来重用代码,调试开发过程中的逻辑错误,在运行时记录日志,以及对代码进行单元测试以消除BUG,并确保稳定性和可靠性。

最近换了好几次电脑,因为最新的是NET 6,所以这个系列往后,都是使用NET6的SDK了。大家更新一下。

本章涵盖以下主题:

  • 编写函数
  • 开发过程中进行调试
  • 在运行时记录日志
  • 进行单元测试
    目录
    • 4.1编写函数
      • 4.1.1 编写乘法表函数
      • 4.1.2 编写带返回值的函数
      • 4.1.3 编写数学函数
        • 1.将数字从序数转换为基数
        • 2.用递归计算阶乘
      • 4.1.4使用XML注释解释函数

4.1编写函数

编程的一条基本原则时不要重复自己(DRY)。

编程时,如果发现自己一遍又一遍地编写同样的语句,就应该把这些语句转换成函数。函数就像完成一项小任务地微型程序。例如,可以编写一个函数来计算营业税,然后在财会类应用程序地许多地方重用该函数。

与程序一样,函数通常也由输入和输出。他们有时被描述为黑盒,在黑盒的一端输入一些原材料,在另一端生成制造的物品。函数一旦创建,就不需要考虑它们是如何工作的。

我们可以十分简单地生成某个数字的乘法表,比如12乘法表:

1*12=12

2*12=24

。。。

12*12=144

你已经在前面地章节中学习了for循环语句,所以当存在规则模式时,比如12乘法表,for循环语句就可以用来生成重复地输出行,如下所示:

for(int row =1;row<=12;row++)
{
    Console.WriteLine($"{row}*12={row*12}");
}

但是我们不想输出12乘法表,而是希望程序更灵活一些,输出任意数字的乘法表。为此可以创建乘法表函数。

4.1.1 编写乘法表函数

下面创建用于回值乘法表的函数

(1)在Code文件夹中创建一个名为Chapter04的文件夹。

(2)启动Visual Studio Code。关闭任何打开的文件夹或工作区,并将当前工作区保存在Chapter04文件夹中,名为Chapter04.code-workspace。

(3)在Chapter04文件夹中创建一个名为WritingFunctions的文件夹,将这个新创建的文件夹添加到Chapter04工作区,并在其中创建一个新的控制台应用程序项目。导航到View=》Terminal、在终端输入dotnet new console。

(4)修改Program.cs如下所示:

using System;
using static System.Console;
namespace WritingFunctions
{
    class Program
    {
         static void TimesTable(byte number)
         {
             WriteLine($"This is the {number} times table:");
             for(int row =1;row<=12;row++)
             {
                WriteLine($"{row} x {number} ={row*number}"); 
             }
             WriteLine();
         }
         static void RunTimesTable()
         {
              bool isNumber;
              do {
                  WriteLine("Enter a number between 0 and 255:");
                  isNumber=byte.TryParse(ReadLine(),out byte number);
                  if(isNumber)
                  {
                      TimesTable(number);
                  }
                  else
                  {
                    
                    WriteLine("You did not enter a valid number!");
                  }
              }
              while (isNumber); 
         }
        static void Main(string[] args)
        {
           RunTimesTable();
        }
    }
}

在上述代码中,请注意下列事项:

  • Console类型已经被静态导入,这样可以简化一些方法的调用,比如WriteLine方法。
  • 我们编写了一个名为TimesTable的函数,但必须吧一个名为number的byte值传递给它。
  • TimesTable函数不向调用者返回值,所以需要使用void关键字来声明它。
  • TimesTable函数使用for循环语句输出传递给它的数字的乘法表。
  • 我们还编写了一个名为RunTimesTable的函数,它会提示用户输入一个数字,然后调用TimesTable函数。将输入的数字传递给TimesTable函数,从而在用户输入有效数字时进行循环。
  • 最后在Main方法中调用RunTimesTable函数。

(5)运行控制台程序。

(6)输入一个数字,例如6,然后查看结果,输出如下所示:

Enter a number between 0 and 255:
11
This is the 11 times table:
1 x 11 =11
2 x 11 =22
3 x 11 =33
4 x 11 =44
5 x 11 =55
6 x 11 =66
7 x 11 =77
8 x 11 =88
9 x 11 =99
10 x 11 =110
11 x 11 =121
12 x 11 =132

4.1.2 编写带返回值的函数

前面写的函数虽然能够执行操作,但却没用返回值。假设需要计算销售税或附加税(VAT)。在欧洲,附加税的税率从瑞士的8%到匈牙利的27%不等。在美国,州销售税从俄勒冈州的0%到加州的8.25%不等。

(1)在Program类中添加一个名为CalculateTax的函数,并使用另一个函数运行CalculateTax函数。在运行之前,请注意以下几点。

  • CalculateTax函数有两个参数:名为amount的参数表示花费的金额;名为twoLetterRegionCode的参数表示花费金额时所在的区域。
  • CalculateTax函数使用switch语句进行计算,然后将所欠的销售税或附加税一decimal值的形式返回;因此,可在函数名之前声明返回值的数据类型。
  • RunCalculateTax函数提示用户输入金额和区域代码,然后调用CalculateTax函数并输出结果。
 static decimal CalculateTax(decimal amount, string twoLetterRegionCode)
        {
            decimal rate = 0.0M;
            switch (twoLetterRegionCode)
            {
                case "CH": //Switzerland
                    rate = 0.08M;
                    break;
                case "DK"://Denmark
                case "NO"://Norway
                    rate = 0.25M;
                    break;
                case "GB"://United Kingdom
                case "FR"://France
                    rate = 0.2M;
                    break;
                case "HU"://Hungary
                    rate = 0.27M;
                    break;
                case "OR"://Oregon
                case "AK"://Alaska
                case "MT"://Montana
                    rate = 0.0M;
                    break;
                case "ND":
                case "WI":
                case "ME":
                case "VA":
                    rate = 0.5M;
                    break;
                case "CA":
                    rate = 0.0825M;
                    break;
                default:
                    rate = 0.06M;
                    break;
            }
            return amount * rate;
        }
        static void RunCaculateTax()
        {
            WriteLine("Enter an amount :");
            string amountInText = ReadLine();
            WriteLine("Enter a two-letter region code:");
            string region = ReadLine();
            if (decimal.TryParse(amountInText, out decimal amount))
            {
                decimal taxToPay = CalculateTax(amount, region);
                WriteLine($"You must pay {taxToPay} in sales tax.");
            }
            else
            {
                WriteLine("You dud bit ebter a valid amount!");
            }
        }

(2)在Main方法中注释掉RunTimesTable方法调用并调用RunSalesTax方法,如下所示:

//RunTimesTable();

​ RunCaculateTax();

(3)运行控制台程序

(4)输入金额(如149)和有效的区域代码(如FR),查看结果,输出如下所示:

Enter an amount :
149
Enter a two-letter region code:
FR
You must pay 29.8 in sales tax.

4.1.3 编写数学函数

尽管可能永远都不需要创建具备数学功能的应用程序,但是几乎每个人都在学校里学习过数学,所以使用数学是学习函数的常用方法。

1.将数字从序数转换为基数

用看来计数的数字成为基数,例如1、2和3;而用于排序的数字是序数,例如第1、第2、第3.

(1)编写一个名为CardinalToOrdinal的函数,将作为基数和int值转换为序数字符串;例如,将1转换为第1,将2转换为第2,等等。

   static string CardinalToOrdinal(int number)
        {
            switch (number)
            {
                case 11:
                case 12:
                case 13:
                    return $"{number}th";
                default:
                    string numberAsText = number.ToString();
                    char lastDigit = numberAsText[numberAsText.Length - 1];
                    string suffix = string.Empty;
                    switch (lastDigit)
                    {
                        case '1':
                            suffix = "st";
                            break;
                        case '2':
                            suffix = "nd";
                            break;
                        case '3':
                            suffix = "rd";
                            break;
                        default:
                            suffix = "th";
                            break;
                    }
                    return $"{number}{suffix}";
            }
        }
        static void RunCardinalToOrdinal()
        {
            for(int number=1;number<=40;number++)
            {
                Write($"{CardinalToOrdinal(number)} ");
            }
            WriteLine();
        }

根据上述代码,请注意下列事项。

  • CardinalToOrdinal函数有一个名为number的int型参数,输出为字符串类型的返回值。
  • 外层的switch语句用于处理输入为11、12和13的情况。
  • 嵌套的switch语句用于处理所有其他情况:如果最后一个数字是1,就使用st作为后缀;如果最后一个数字是2,就使用nd作为后缀;如果最后一个数字是3,就使用rd作为后缀;如果最后一个数字是除了1、2、3以外的其他数字,就是要th作为后缀。
  • RunCardinalToOrdinal函数使用for语句从1循环到40,为每个数字调用CardianlToOrdinal函数,并将返回的字符串写入控制台,中间用空格字符分割。

(2)在Main方法中注释掉RunSalesTax方法,调用RunCardianlOrdinal方法,如下所示:

//RunTimesTable();

​ //RunCaculateTax();

​ RunCardinalToOrdinal();

(3)运行控制台应用程序并查看结果,输出如下:

1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th 12th 13th 14th 15th 16th 17th 18th 19th 20th 21st 22nd 23rd 24th 25th 26th 27th 28th 29th 30th 31st 32nd 33rd 34th 35th 36th 37th 38th 39th 40th

2.用递归计算阶乘

下面编写函数Factorial,计算作为参数传递给它的int型整数的阶乘。这里使用一种称为递归的技术,这意味着需要在Factorial函数的实现中直接或间接的调用自身。

(1)先添加一个名为Factorial的函数,再添加另一个名为RunFactorial的函数,后者用于调用前者,如下所示:

static int Factorial(int number)
        {
            if (number < 1)
            {
                return 0;
            }
            else if (number == 1)
            {
                return 1;
            }
            else
            {
                return number * Factorial(number - 1);
            } 
        }
        static void RunFactorial()
        {
            bool isNumber;
            do
            {
                Write("Enter a number:");
                isNumber = int.TryParse(Console.ReadLine(), out int number);
                if (isNumber)
                {
                    WriteLine($"{number:N0}!={Factorial(number):N0}");
                }
                else
                {
                    WriteLine("You did not enter a valid number!");
                }
            }
            while (isNumber);
        }

和以前一样,上述代码中有如下几个值得注意的地方。

  • 如果输入的数字为0或复数,那么Factorial函数返回0。
  • 如果输入的数字是1,那么Factorial函数返回1,因此停止调用自身。如果输入的数字大于1,那么Factorial函数将该数乘以Factorial函数调用本身的结果,并传递比该数小1的数。
  • RunFactorial函数提示用户输入一个数字,调用Factorial函数,然后输出结果,可使用代码N0对结果进行格式化。N0表示数字格式,并使用千位分隔符,没有小数位。只要输入了另一个数字,就会在循环中重复。
  • 在Main方法中注释掉RunCardinalToOrdinal方法调用,并调用RunFactorial方法。

(2)运行控制台程序。

(3)输入数字3、5、31和32,并查看结果,输出如下所示:

Enter a number:3
3!=6
Enter a number:5
5!=120
Enter a number:31
31!=738,197,504
Enter a number:32
32!=-2,147,483,648

从上面的输出中可以看到,32及更大数字的阶乘会溢出int类型,因为结果太大了。

4.1.4使用XML注释解释函数

默认情况下当调用CardinalToOrdinal这样的函数时,Visual Studio Code将显示带有基本信息的工具提示。

下面通过添加额外的信息来改进工具提示。

(1)如果没有安装C# XML文档注释扩展,安装Visual Studio Code扩展,在扩展中搜索C#

(2)在位于CardinalToOrdinal函数上方的那些行的行首输入三个斜杠,从而将他们扩展为XML注释并识别出名为number的参数


喜欢 (0)