C#入门篇5

目录

一、常量

二、枚举

 1、枚举类型和int以及string类型之间的转换

2、注意事项

强制转换(Explicit Casting):

Enum.Parse 和 Enum.TryParse:

 三、结构

定义方式:结构体使用 struct 关键字进行定义。结构体通常用于表示小型、轻量级的数据类型

 值类型:结构体是值类型,这意味着它们在赋值或传递时会被复制。每个结构体的实例都具有独立的值

四、一维数组

1、语法:

五、方法(函数)

1、语法:

 六、out参数

1、概念

2、定义

3、注意事项

七、ref参数

1、概念:

2、ref 参数的定义

3、注意事项

 八、params可变参数

1、概念:

2、params 参数的定义

3、注意事项:

九、方法的重载

1、概念

2、定义

 3、注意事项

十、方法的递归

1、概念

2、定义

 3、注意事项


一、常量

概念:常量(const)是指一个在编译时就确定其值且在程序运行期间不会改变的变量(比如银行系统)

声明方式:

const  变量类型 变量名 = 值

const int MaxValue = 100;
const string WelcomeMessage = "Hello, World!";
//MaxValue = 100 ;不能给常量重新赋值

二、枚举

概念:枚举(enum)是一种特殊的值类型,用于定义一组具有名称的常量。这些常量通常代表一个有意义的整数值

定义方式:

枚举使用 enum 关键字进行定义。每个枚举成员都有一个名称和对应的整数值。

[ ]:表示可写可不写

public:访问修饰符

[public] enum 枚举名
{
    值1,    // 默认值为0
    值2,    // 默认值为1
    .........
    值3   // 默认值为2
  
}
public enum Colors
{
    Red,
    Green,
    Blue
}

public class Program
{
    public static void Main()
    {
        Colors myColor = Colors.Green;

        switch (myColor)
        {
            case Colors.Red:
                Console.WriteLine("The color is Red.");
                break;
            case Colors.Green:
                Console.WriteLine("The color is Green.");
                break;
            case Colors.Blue:
                Console.WriteLine("The color is Blue.");
                break;
        }
    }
}

 1、枚举类型和int以及string类型之间的转换

/*将 int 转换为枚举类型:
使用显式类型转换(强制转换)可以将整数值转换为对应的枚举值:*/
public enum DaysOfWeek
{
    Sunday = 1,
    Monday = 2,
    Tuesday = 3,
    Wednesday = 4,
    Thursday = 5,
    Friday = 6,
    Saturday = 7
}

public class Program
{
    public static void Main()
    {
        int dayNumber = 5;
        DaysOfWeek day = (DaysOfWeek)dayNumber;
        Console.WriteLine(day); // 输出:Thursday
    }
}
/*将枚举类型转换为 int:
可以直接将枚举值转换为 int 类型*/
public class Program
{
    public static void Main()
    {
        DaysOfWeek day = DaysOfWeek.Friday;
        int dayNumber = (int)day;
        Console.WriteLine(dayNumber); // 输出:6
    }
}
/*将枚举转换为 string:
使用 ToString() 方法可以将枚举值转换为其名称的字符串*/

public class Program
{
    public static void Main()
    {
        DaysOfWeek day = DaysOfWeek.Monday;
        string dayName = day.ToString();
        Console.WriteLine(dayName); // 输出:Monday
    }
}
public class Program
{
    public static void Main()
    {
        string dayName = "Wednesday";
        
        // 使用 Enum.Parse()
        DaysOfWeek day = (DaysOfWeek)Enum.Parse(typeof(DaysOfWeek), dayName);
        Console.WriteLine(day); // 输出:Wednesday

        // 使用 Enum.TryParse()
        if (Enum.TryParse(dayName, out DaysOfWeek parsedDay))
        {
            Console.WriteLine(parsedDay); // 输出:Wednesday
        }
        else
        {
            Console.WriteLine("Invalid day name.");
        }
    }
}

2、注意事项

  • 强制转换(Explicit Casting)
    • 在将 int 转换为枚举时,如果 int 的值不在枚举定义的范围内,强制转换不会抛出异常,但会得到不符合预期的枚举值。
    • 在将枚举转换为 int 时,得到的是枚举成员定义的整数值。
  • Enum.Parse 和 Enum.TryParse
    • Enum.Parse 会抛出 ArgumentException 如果字符串值不匹配任何枚举成员。
    • Enum.TryParse 不会抛出异常,它通过返回值来指示转换是否成功,并通过 out 参数返回解析的枚举值。

 三、结构

  概念:结构体(struct)是一种值类型的数据结构,用于封装一组相关的数据。结构体与类(class)类似,但它们在内存管理、性能和使用场景上有一些显著的不同点。

  • 定义方式:结构体使用 struct 关键字进行定义。结构体通常用于表示小型、轻量级的数据类型
public struct Point
{
    public int X;
    public int Y; //字段:存储数据,程序运行时可以存储一个值,而字段可以存多个值


    public Point(int x, int y) //构造函数
    {
        X = x;
        Y = y;
    }

    public override string ToString() //方法
    {
        return $"({X}, {Y})";
    }
}
  •  值类型:结构体是值类型,这意味着它们在赋值或传递时会被复制。每个结构体的实例都具有独立的值
public class Program
{
    public static void Main()
    {
        Point p1 = new Point(1, 2);
        Point p2 = p1; // 复制 p1 的值
        p2.X = 10;

        Console.WriteLine(p1); // 输出:(1, 2)
        Console.WriteLine(p2); // 输出:(10, 2)
    }
}
  1. 内存管理:结构体存储在栈上(当作为局部变量时)或嵌入在其他对象中(当作为字段时),这使得2、它们通常比类对象(存储在堆上)具有更高的性能。由于结构体是值类型,它们不具有继承的特性,也不能使用类的特性(如虚方法)
  2. 构造函数:结构体可以有构造函数,但必须为所有字段提供初始化值。结构体不能有无参数构造函数,编译器自动提供一个默认的无参数构造函数,所有字段都会初始化为其默认值。
  3. 方法和属性:结构体可以包含方法、属性、字段、事件和构造函数。它们也可以实现接口,但不能继承自其他结构体或类
  4. 比较和相等:由于结构体是值类型,它们的比较是基于值的。Equals() 方法和 == 运算符会比较结构体的所有字段值是否相等。

public class Program
{
    public static void Main()
    {
        Rectangle r1 = new Rectangle(4, 5);
        Rectangle r2 = new Rectangle(4, 5);

        Console.WriteLine(r1.Equals(r2)); // 输出:True
        Console.WriteLine(r1 == r2); // 输出:True
    }
}

 示例代码:

public struct Circle
{
    public double Radius { get; set; }

    public Circle(double radius)
    {
        Radius = radius;
    }

    public double Area()
    {
        return Math.PI * Radius * Radius;
    }

    public override string ToString()
    {
        return $"Circle with Radius: {Radius}";
    }
}

public class Program
{
    public static void Main()
    {
        Circle c = new Circle(5.0);
        Console.WriteLine(c); // 输出:Circle with Radius: 5
        Console.WriteLine($"Area: {c.Area()}"); // 输出:Area: 78.53981633974483
    }
}

四、一维数组

概念:数组是一种数据结构,用于存储固定大小的、相同类型的元素的集合。它允许你通过索引来访问和操作这些元素。数组的大小在创建时确定,并且不能在运行时动态调整。

1、语法:

数组类型[ ] 数组名 = new 数组类型[数组长度](数组的长度一旦固定了,就不能再被改变)

using System;

class Program
{
    static void Main()

        //数组的定义方法
    {
        int[] numbers = new int[5]; 

        int[] numbers1 = new int[] { 1, 2, 3, 4, 5 }; 

        int[] numbers2 = { 1, 2, 3, 4, 5 }; 


        int[] numbers3 =new int[3] { 1, 2, 3};
           
        //数组的访问

        int firstNumber = numbers[0]; // 访问第一个元素,值为 1

        numbers[2] = 10; // 修改第三个元素的值为 10

        // 使用 for 循环 遍历数组
        for (int i = 0; i < numbers.Length; i++)
        {
            Console.WriteLine(numbers[i]);
        }

        Console.ReadKey();



    }
}

五、方法(函数)

 概念:函数就是将一堆代码进行重用的一种机制

1、语法:

[public] static 返回值类型 方法名([参数列表])

{

        方法体;
}

调用方法:类名.方法名(参数);(如果在同一个类中可省略类名)

public class Program
{
    // 定义一个无返回值的方法,接受两个整数参数并打印它们的和
    public static void PrintSum(int a, int b)
    {
        int sum = a + b;
        Console.WriteLine("Sum: " + sum);
    }

    public static void Main()
    {
        // 调用 PrintSum 方法,传递两个整数参数
        PrintSum(5, 10); // 输出:Sum: 15
    }
}

 六、out参数

1、概念

out 关键字用于将参数按引用传递到方法中,允许方法初始化并返回一个新的值给调用者。与 ref 参数不同,out 参数在传递给方法之前不需要初始化。out 参数主要用于在方法中返回多个值或者处理某些需要修改的情况。

2、定义
  • 定义:在方法的参数列表中使用 out 关键字,表示该参数是按引用传递的,并且在方法内部必须被初始化。
  • 调用:调用方法时,需要使用 out 关键字来标识该参数。
  • 初始化:传递给 out 参数的变量不需要在调用前初始化,因为方法内部会给它赋值。
/*TryParse 方法尝试将字符串转换为整数。如果转换成功,返回 true 并将转换结果赋值给 out 参数 number;否则返回 false。
在 Main 方法中,result 变量被声明但未初始化,随后被 TryParse 方法初始化并赋值。如果转换成功,result 将包含转换后的整数值。*/
using System;

class Program
{
    static void Main()
    {
        int result;
        bool success = TryParse("123", out result);
        if (success)
        {
            Console.WriteLine($"Parsed value: {result}");
        }
        else
        {
            Console.WriteLine("Failed to parse the input.");
        }
    }

    static bool TryParse(string input, out int number)
    {
        return int.TryParse(input, out number);
    }
}
/*CalculateValues 方法计算两个整数的和与积,并通过 out 参数返回结果。
在 Main 方法中,调用 CalculateValues 时,sum 和 product 变量用于接收计算结果,CalculateValues 方法对它们进行初始化。*/
using System;

class Program
{
    static void Main()
    {
        int sum, product;
        CalculateValues(5, 3, out sum, out product);
        Console.WriteLine($"Sum: {sum}, Product: {product}");
    }

    static void CalculateValues(int a, int b, out int sum, out int product)
    {
        sum = a + b;
        product = a * b;
    }
}
/*CalculateDifferenceAndSum 方法计算两个整数的差值和和,并通过 ref 和 out 参数返回结果。
difference 使用 ref 传递,表示输入值减去当前值,sum 使用 out 传递,表示输入值与当前值的和。在方法内部进行初始化并返回。*/
using System;

class Program
{
    static void Main()
    {
        int value1 = 10;
        int value2;
        bool result = CalculateDifferenceAndSum(15, ref value1, out value2);
        Console.WriteLine($"Difference: {value1}, Sum: {value2}");
        Console.WriteLine($"Calculation successful: {result}");
    }

    static bool CalculateDifferenceAndSum(int input, ref int difference, out int sum)
    {
        sum = input + difference;
        difference = input - difference;
        return true;
    }
}
3、注意事项
  • 初始化out 参数在方法内部必须被初始化,否则编译器会报错。调用方法前不需要初始化。
  • 方法定义和调用一致:在方法定义和调用中,out 关键字必须都出现。
  • 避免混淆:虽然 out 和 ref 都是按引用传递参数,但 ref 参数需要在传递前初始化,而 out 参数在传递前不需要初始化,只需要在方法内部被赋值。

七、ref参数

1、概念:

ref 关键字用于将参数按引用传递给方法,这样方法内部对参数的修改会反映到调用者传递的变量上。使用 ref 参数可以让方法修改传入的变量的值,而不仅仅是读取它。

2、ref 参数的定义
  • 定义:在方法的参数列表中使用 ref 关键字,指明该参数是按引用传递的。
  • 调用:在调用方法时,也需要使用 ref 关键字来标识该参数。
  • 初始化:传递给 ref 参数的变量在使用之前必须初始化,因为方法内部可能会修改它的值。
/*number 变量在 Main 方法中被初始化为 10。
在调用 ModifyValue 方法时,number 被传递为 ref 参数,因此方法内部的修改(value += 10)会影响到 number。
方法执行后,number 的值变为 20。*/
using System;

class Program
{
    static void Main()
    {
        int number = 10;
        Console.WriteLine($"Before: {number}");
        ModifyValue(ref number);
        Console.WriteLine($"After: {number}");
    }

    static void ModifyValue(ref int value)
    {
        value += 10;
    }
}
/*a 和 b 在 Main 方法中被初始化。
调用 Swap 方法时,将 a 和 b 作为 ref 参数传递。这样,Swap 方法可以直接修改这两个变量的值。
Swap 方法交换了 a 和 b 的值,最终输出 a = 10 和 b = 5*/

using System;

class Program
{
    static void Main()
    {
        int a = 5;
        int b = 10;
        Console.WriteLine($"Before: a = {a}, b = {b}");
        Swap(ref a, ref b);
        Console.WriteLine($"After: a = {a}, b = {b}");
    }

    static void Swap(ref int x, ref int y)
    {
        int temp = x;
        x = y;
        y = temp;
    }
}
3、注意事项
  1. 初始化:在将变量作为 ref 参数传递之前,必须对其进行初始化。
  2. 调用和定义一致:在方法调用和方法定义中,都必须使用 ref 关键字。
  3. 方法内的修改ref 参数的修改在方法外部是可见的,因此需要谨慎使用,以避免意外修改数据。

 八、params可变参数

1、概念:

params 关键字用于允许一个方法接受可变数量的参数。使用 params 关键字时,方法可以接收零个或多个参数,并将它们作为一个数组处理。

2、params 参数的定义
  • 位置params 参数必须是方法参数列表中的最后一个参数。
  • 类型params 参数的类型必须是数组类型。例如,你可以使用 int[]string[] 等类型。
  • 传递:当调用使用 params 关键字定义的方法时,可以传递多个值,也可以传递一个数组或不传递任何值。
/*PrintNumbers 方法定义了一个 params 参数 numbers,它可以接收任意数量的 int 参数。
在 Main 方法中,PrintNumbers 被调用了三次:一次传递多个参数,一次传递一个数组,一次不传递任何参数。
无论传递了多少参数,PrintNumbers 方法都会正确地打印这些参数。*/
using System;

class Program
{
    static void Main()
    {
        // 调用方法时传递多个参数
        PrintNumbers(1, 2, 3, 4, 5);
        
        // 调用方法时传递一个数组
        int[] numbers = { 10, 20, 30 };
        PrintNumbers(numbers);
        
        // 调用方法时不传递任何参数
        PrintNumbers();
    }

    static void PrintNumbers(params int[] numbers)
    {
        foreach (int number in numbers)
        {
            Console.Write(number + " ");
        }
        Console.WriteLine();
    }
}
/*ConcatenateAndPrint 方法接收一个字符串 prefix 和一个 params 参数 numbers。
调用 ConcatenateAndPrint 时,字符串 prefix 是第一个参数,后面的整数值被作为数组传递给 numbers 参数。
方法输出了前缀和所有整数值。*/
using System;

class Program
{
    static void Main()
    {
        // 传递一个额外的字符串参数和多个整数参数
        ConcatenateAndPrint("Numbers:", 1, 2, 3, 4, 5);
    }

    static void ConcatenateAndPrint(string prefix, params int[] numbers)
    {
        Console.Write(prefix + " ");
        foreach (int number in numbers)
        {
            Console.Write(number + " ");
        }
        Console.WriteLine();
    }
}
3、注意事项:
  1. 只能有一个 params 参数:一个方法中只能有一个 params 参数,并且它必须是参数列表中的最后一个。
  2. 可以传递数组:你可以直接传递一个数组给 params 参数,这会将数组作为参数传递到方法中。
  3. 类型一致性params 参数的类型必须与方法定义中的数组类型一致。

九、方法的重载

1、概念

方法重载(Method Overloading) 是一种允许在同一个类中定义多个方法,这些方法具有相同的名称但参数列表不同的技术。方法重载可以使代码更具可读性和可维护性,因为它允许使用相同的方法名称来执行类似但参数不同的操作。 

2、定义
  • 定义:方法重载是在同一个类中定义多个具有相同名称但参数列表(参数的类型、数量或顺序)不同的方法。这些方法具有不同的签名。
  • 签名:方法的签名由方法名称和参数列表组成。返回类型不作为重载的区分标准。
  • 调用:根据传递给方法的参数类型和数量,编译器会选择匹配的方法进行调用。
/*PrintMessage 方法被重载两次,一次接受一个字符串参数,另一次接受两个字符串参数。
根据传递的参数数量,编译器会选择合适的重载方法进行调用。在 Main 方法中,调用 PrintMessage("Hello") 使用的是第一个重载,而调用 PrintMessage("Hello", "World") 使用的是第二个重载。*/
using System;

class Program
{
    static void Main()
    {
        PrintMessage("Hello");
        PrintMessage("Hello", "World");
    }

    static void PrintMessage(string message)
    {
        Console.WriteLine(message);
    }

    static void PrintMessage(string message1, string message2)
    {
        Console.WriteLine($"{message1} {message2}");
    }
}
/*Add 方法被重载三次,分别处理整数、浮点数和字符串的加法。
根据传递的参数类型,编译器会选择匹配的重载方法。在 Main 方法中,Add(5, 10) 调用整型重载,Add(3.5, 2.5) 调用浮点数重载,而 Add("Hello ", "World") 调用字符串重载。*/
using System;

class Program
{
    static void Main()
    {
        Console.WriteLine(Add(5, 10));         // 整数相加
        Console.WriteLine(Add(3.5, 2.5));       // 浮点数相加
        Console.WriteLine(Add("Hello ", "World")); // 字符串拼接
    }

    static int Add(int a, int b)
    {
        return a + b;
    }

    static double Add(double a, double b)
    {
        return a + b;
    }

    static string Add(string a, string b)
    {
        return a + b;
    }
}
/*Display 方法被重载两次,一次参数顺序为 string 和 int,另一次为 int 和 string。
根据参数的顺序,编译器会选择合适的重载方法。在 Main 方法中,Display("Hello", 10) 调用第一个重载,而 Display(10, "Hello") 调用第二个重载。*/
using System;

class Program
{
    static void Main()
    {
        Display("Hello", 10);
        Display(10, "Hello");
    }

    static void Display(string text, int number)
    {
        Console.WriteLine($"Text: {text}, Number: {number}");
    }

    static void Display(int number, string text)
    {
        Console.WriteLine($"Number: {number}, Text: {text}");
    }
}
 3、注意事项
  1. 参数列表必须不同:要重载方法,必须确保方法的参数列表(包括参数类型、数量或顺序)不同。如果仅更改返回类型而参数列表相同,编译器会报错。
  2. 可读性:过多的重载可能会导致代码混乱,影响可读性。合理使用重载能够提升代码的清晰度和简洁性。
  3. 编译器选择:编译器会根据方法的签名和传递的参数类型选择最匹配的方法。如果存在多个匹配的方法,可能会导致编译错误或无法确定调用的方法。

十、方法的递归

1、概念

方法递归(Recursion)是指在一个方法的定义中直接或间接调用该方法自身的编程技巧。递归可以使解决某些问题变得更加简洁和直观,特别是当问题可以分解为相似的子问题时。使用递归时,通常需要定义一个或多个基准条件(base cases)来终止递归,以防止无限循环。

2、定义
  • 递归方法:一个方法在其执行过程中调用自身。
  • 基准条件:递归的终止条件,防止递归无限进行。每个递归方法必须有至少一个基准条件,以确保递归最终会停止。
  • 递归条件:方法在执行时调用自身的条件,通常会对问题进行简化或分解。
/*Factorial 方法计算一个整数的阶乘。
基准条件是 n == 0 时返回 1。
递归条件是 n * Factorial(n - 1),即将问题分解为更小的子问题。*/
using System;

class Program
{
    static void Main()
    {
        int number = 5;
        Console.WriteLine($"{number}! = {Factorial(number)}");
    }

    static int Factorial(int n)
    {
        // 基准条件:如果 n 为 0,则返回 1
        if (n == 0)
        {
            return 1;
        }
        // 递归条件:n! = n * (n-1)!
        else
        {
            return n * Factorial(n - 1);
        }
    }
}
/*Fibonacci 方法计算第 n 个斐波那契数。
基准条件是 n == 0 和 n == 1 时返回 0 和 1。
递归条件是 Fibonacci(n - 1) + Fibonacci(n - 2),即将问题分解为更小的子问题。*/
using System;

class Program
{
    static void Main()
    {
        int n = 10;
        Console.WriteLine($"Fibonacci({n}) = {Fibonacci(n)}");
    }

    static int Fibonacci(int n)
    {
        // 基准条件:F(0) = 0 和 F(1) = 1
        if (n == 0)
        {
            return 0;
        }
        else if (n == 1)
        {
            return 1;
        }
        // 递归条件:F(n) = F(n-1) + F(n-2)
        else
        {
            return Fibonacci(n - 1) + Fibonacci(n - 2);
        }
    }
}
/*Reverse 方法反转给定的字符串。
基准条件是字符串长度小于等于 1 时直接返回字符串。
递归条件是 Reverse(str.Substring(1)) + str[0],即对字符串的子串递归反转,并将当前字符添加到末尾。*/
using System;

class Program
{
    static void Main()
    {
        string str = "hello";
        Console.WriteLine($"Reversed string: {Reverse(str)}");
    }

    static string Reverse(string str)
    {
        // 基准条件:空字符串或只有一个字符
        if (str.Length <= 1)
        {
            return str;
        }
        // 递归条件:反转字符串的递归部分 + 当前字符
        else
        {
            return Reverse(str.Substring(1)) + str[0];
        }
    }
}
 3、注意事项
  1. 基准条件:递归方法必须包含基准条件,确保递归能够停止。否则,可能导致无限递归和栈溢出错误。
  2. 栈空间:递归调用会消耗栈空间,因此在处理深度递归时要注意性能和内存消耗。对于很深的递归,可能会导致栈溢出。
  3. 性能:某些递归算法的性能可能不如迭代方法,特别是对于较大规模的问题。考虑使用动态规划或其他优化技术来提高性能。

你可能感兴趣的:(开发语言,c#入门)