从Java开发者到.NET Core初级工程师学习路线:C#语言基础

07-09 999阅读

1. C#语言基础

1.1 C#语法概览

欢迎来到C#的世界!对于刚从Java转过来的开发者来说,你会发现C#和Java有很多相似之处,但C#也有其独特的魅力和强大之处。让我们一起来探索C#的基本语法,并比较一下与Java的异同。

从Java开发者到.NET Core初级工程师学习路线:C#语言基础
(图片来源网络,侵删)

程序结构

C#程序的基本结构与Java非常相似。这里是一个简单的C#程序:

using System;
namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

对比Java的版本:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

你会发现,两者的结构非常相似。主要的区别在于:

  1. C#使用using关键字导入命名空间,而Java使用import。
  2. C#的Main方法是static void Main(string[] args),而Java是public static void main(String[] args)。
  3. C#使用Console.WriteLine()输出,Java使用System.out.println()。

在c# 9的最新语法上还可以更简洁,是的没错,只需要一行代码,不需要写命名空间,类,方法,直接编写代码,当然这个方式只存在c#9以上的版本。

Console.WriteLine("Hello, World!");

命名约定

C#和Java的命名约定有些许不同:

  • C#中,方法名和属性名通常使用PascalCase(如CalculateTotal)。
  • 局部变量和参数使用camelCase(如totalAmount)。
  • 接口名称以"I"开头(如IDisposable)。

    而Java中:

    • 方法名和变量名都使用camelCase。
    • 接口名称不需要特殊前缀。

      数据类型

      C#和Java的基本数据类型很相似,但也有一些区别:

      C#:

      int x = 10;
      long y = 100L;
      float f = 3.14f;
      double d = 3.14;
      decimal m = 100.50m;
      bool isTrue = true;
      char c = 'A';
      string s = "Hello";
      

      Java:

      int x = 10;
      long y = 100L;
      float f = 3.14f;
      double d = 3.14;
      boolean isTrue = true;
      char c = 'A';
      String s = "Hello";
      

      注意C#特有的decimal类型,它提供了更高精度的小数计算,特别适合金融相关的应用。

      数组

      C#和Java的数组声明稍有不同:

      C#:

      int[] numbers = new int[5];
      string[] names = { "Alice", "Bob", "Charlie" };
      

      Java:

      int[] numbers = new int[5];
      String[] names = { "Alice", "Bob", "Charlie" };
      

      控制结构

      C#和Java的控制结构几乎完全相同:

      // if语句
      if (condition)
      {
          // code
      }
      else if (anotherCondition)
      {
          // code
      }
      else
      {
          // code
      }
      // for循环
      for (int i = 0; i  
      

      这些结构在Java中的写法完全相同。

      异常处理

      C#和Java的异常处理也非常相似:

      C#:

      try
      {
          // 可能抛出异常的代码
      }
      catch (SpecificException ex)
      {
          // 处理特定异常
      }
      catch (Exception ex)
      {
          // 处理一般异常
      }
      finally
      {
          // 总是要执行的代码
      }
      

      Java的异常处理结构完全相同。

      注释

      C#和Java的注释方式也是一样的:

      // 这是单行注释
      /*
      * 这是多行注释
      */
      /// 
      /// 这是XML文档注释,类似于Java的Javadoc
      /// 
      

      小结

      通过这个概览,你可以看到C#和Java在语法上有很多相似之处。这意味着作为一个Java开发者,你可以相对轻松地过渡到C#。然而,C#也有其独特的特性和语法糖,使得某些任务更加简洁和高效。

      在接下来的章节中,我们将深入探讨C#的各个方面,包括它独特的特性如属性、事件、委托等。这些概念可能对Java开发者来说比较新,但它们是C#强大功能的关键所在。记住,学习一门新的语言不仅是学习语法,更是学习一种新的思维方式。让我们继续我们的C#学习之旅吧!

      1.2 变量和数据类型

      在C#中,变量和数据类型是编程的基础。对于从Java转过来的开发者来说,你会发现很多熟悉的概念,但C#也有一些独特的特性。让我们深入探讨C#的变量和数据类型,并与Java进行比较。

      变量声明

      C#和Java的变量声明方式非常相似:

      C#:

      int age = 25;
      string name = "Alice";
      bool isStudent = true;
      

      Java:

      int age = 25;
      String name = "Alice";
      boolean isStudent = true;
      

      主要区别在于:

      1. C#使用string(小写),而Java使用String(大写)。
      2. C#使用bool,而Java使用boolean。

      基本数据类型

      C#和Java都有类似的基本数据类型,但C#提供了更多的选择:

      C# 类型Java 类型大小范围
      sbytebyte8位-128 到 127
      byte-8位0 到 255
      shortshort16位-32,768 到 32,767
      ushort-16位0 到 65,535
      intint32位-2^31 到 2^31-1
      uint-32位0 到 2^32-1
      longlong64位-2^63 到 2^63-1
      ulong-64位0 到 2^64-1
      floatfloat32位±1.5x 10^-45 到 ±3.4 x 10^38
      doubledouble64位±5.0 × 10^-324 到 ±1.7 × 10^308
      decimal-128位±1.0 x 10^-28 到 ±7.9 x 10^28
      charchar16位U+0000 到 U+FFFF
      boolboolean8位true或 false

      注意C#提供了无符号整数类型(byte, ushort, uint, ulong)和decimal类型,这些在Java中是没有的。

      值类型和引用类型

      C#和Java都区分值类型和引用类型,但C#的处理更加灵活:

      1. 值类型(Value Types):

        • 在C#中,所有的基本数据类型(int, float, bool等)和struct都是值类型。
        • 值类型直接存储它们的数据。
        • 引用类型(Reference Types):

          • 类(class)、接口(interface)、委托(delegate)和数组(array)是引用类型。
          • 引用类型存储对其数据(对象)的引用。

      C#独特之处:

      • C#允许使用struct关键字创建自定义值类型。
      • C#的string虽然是引用类型,但具有值类型的一些特性(如不可变性)。

        可空类型

        C#引入了可空类型的概念,这在Java中是没有的:

        int? nullableInt = null;
        bool? nullableBool = null;
        

        可空类型允许值类型也可以赋值为null,这在处理数据库或用户输入时非常有用。

        var关键字

        C#提供了var关键字用于隐式类型声明:

        var x = 10; // 编译器推断x为int类型
        var name = "Alice"; // 编译器推断name为string类型
        

        Java从Java 10开始引入了类似的var关键字,但使用范围更受限制。

        常量

        C#使用const关键字声明常量:

        const int MaxValue = 100;
        const string AppName = "MyApp";
        

        Java使用final关键字:

        final int MAX_VALUE = 100;
        final String APP_NAME = "MyApp";
        

        枚举

        C#和Java都支持枚举,但C#的枚举更加灵活:

        C#:

        enum Days
        {
            Monday,
            Tuesday,
            Wednesday,
            Thursday,
            Friday,
            Saturday,
            Sunday
        }
        // 可以指定底层类型和值
        enum Status : byte
        {
            Active = 1,
            Inactive = 0,Suspended = 2
        }
        

        Java:

        enum Days {
            MONDAY,
            TUESDAY,
            WEDNESDAY,
            THURSDAY,
            FRIDAY,
            SATURDAY,
            SUNDAY
        }
        

        C#的枚举可以指定底层类型,而Java的枚举实际上是特殊的类。

        类型转换

        C#提供了多种类型转换方法:

        1. 隐式转换:

          int x = 10;
          long y = x; // 隐式转换,不需要显式转换
          
        2. 显式转换(强制类型转换):

          doubled = 3.14;
          int i = (int)d; // 显式转换,可能会损失精度
          
        3. 使用Convert类:

          string s = "123";
          int i = Convert.ToInt32(s);
          
        4. 使用Parse方法:

          string s = "3.14";
          double d = double.Parse(s);
          
        5. TryParse方法(安全转换):

          string s = "123";
          int result;
          if (int.TryParse(s, out result))
          {
              Console.WriteLine($"Converted value: {result}");
          }
          else
          {
              Console.WriteLine("Conversion failed");
          }
          

        Java的类型转换相对简单一些,主要依赖于强制类型转换和包装类的方法。

        小结

        虽然C#和Java在变量和数据类型方面有很多相似之处,但C#提供了更多的选择和灵活性。C#的可空类型、更丰富的基本数据类型、更灵活的枚举和方便的类型转换方法,都为开发者提供了更多的工具来处理各种数据场景。

        作为一个从Java转向C#的开发者,你会发现这些额外的特性可以让你的代码更加简洁和表达力更强。在实际编程中,合理利用这些特性可以提高代码的可读性和性能。

        在接下来的学习中,我们将深入探讨C#的更多高级特性,如属性、索引器、泛型等。这些概念将进一步展示C#相对于Java的独特优势。继续保持学习的热情,你会发现C#是一个功能丰富、富有表现力的语言!

        1.3 运算符和表达式

        C#的运算符和表达式与Java有很多相似之处,但也有一些独特的特性。让我们深入了解C#的运算符和表达式,并与Java进行比较。

        算术运算符

        C#和Java的算术运算符基本相同:

        • 加法 (+)
        • 减法 (-)
        • 乘法 (*)
        • 除法 (/)
        • 取模 (%)

          示例:

          int a = 10, b = 3;
          int sum = a + b;      // 13
          int difference = a - b; // 7
          int product = a * b;   // 30
          int quotient = a / b;  // 3 (整数除法)
          int remainder = a % b; // 1
          

          注意:C#和Java在整数除法时都会舍去小数部分,如果要得到精确结果,至少有一个操作数应该是浮点数。

          赋值运算符

          C#和Java的赋值运算符也基本相同:

          • 简单赋值 (=)
          • 复合赋值 (+=, -=, *=, /=, %=)

            C#特有的复合赋值运算符:

            • ??= (空合并赋值运算符,C# 8.0引入)

              示例:

              int x = 5;
              x += 3;  // 等同于 x = x + 3
              x -= 2;  // 等同于 x = x - 2
              string name = null;
              name ??= "John";  // 如果name为null,赋值为"John"
              

              比较运算符

              C#和Java的比较运算符完全相同:

              • 等于 (==)
              • 不等于 (!=)
              • 大于 (>)
              • 小于 (=)
              • 小于等于 ( b);// false bool isLess = (a = b); // false bool isLessOrEqual = (a >>)

                示例:

                int a = 60;// 二进制: 0011 1100
                int b = 13;  // 二进制: 0000 1101
                int c = a & b;  // 12(二进制: 0000 1100)
                int d = a | b;  // 61 (二进制: 0011 1101)
                int e = a ^ b;  // 49 (二进制: 0011 0001)
                int f = ~a;     // -61 (二进制: 1100 0011, 补码表示)
                int g = a > 2; // 15 (二进制: 0000 1111)
                

                条件运算符

                C#和Java都有三元条件运算符:

                int a = 10, b = 20;
                int max = (a > b) ? a : b;  // 20
                

                C#特有的条件运算符:

                • 空合并运算符 (??)
                • 空条件运算符(?.)

                  示例:

                  string name = null;
                  string displayName = name ?? "Guest";  // "Guest"
                  class Person
                  {
                      public string Name { get; set; }
                  }
                  Person person = null;
                  int? nameLength = person?.Name?.Length;  // null
                  

                  类型测试运算符

                  C#提供了一些Java中没有的类型测试运算符:

                  • is 运算符:检查对象是否与特定类型兼容
                  • as 运算符:执行类型转换,如果转换失败,返回null

                    示例:

                    object obj = "Hello";
                    if (obj is string)
                    {
                        Console.WriteLine("obj is a string");
                    }
                    string str = obj as string;
                    if (str != null)
                    {
                        Console.WriteLine($"The string is: {str}");
                    }
                    

                    Lambda 表达式

                    C#和Java都支持Lambda表达式,但语法略有不同:

                    C#:

                    Func square = x => x * x;
                    int result = square(5);  // 25
                    

                    Java:

                    Function square = x -> x * x;
                    int result = square.apply(5);  // 25
                    

                    空合并运算符(??)

                    C#特有的空合并运算符可以简化处理可能为null的情况:

                    string name = null;
                    string displayName = name ?? "Guest";  // "Guest"
                    

                    在Java中,你可能需要这样写:

                    String name = null;
                    String displayName = (name != null) ? name : "Guest";
                    

                    表达式体成员 (Expression-bodied members)

                    C#允许使用更简洁的语法来定义属性和方法:

                    public class Circle
                    {
                        public double Radius { get; set; }
                        public double Diameter => Radius * 2;
                        public double CalculateArea() => Math.PI * Radius * Radius;
                    }
                    

                    这种语法在Java中是不存在的。

                    字符串插值

                    C#提供了非常方便的字符串插值语法:

                    string name = "Alice";
                    int age = 30;
                    string message = $"My name is {name} and I am {age} years old.";
                    

                    Java在较新的版本中也引入了类似的功能,但语法不同:

                    String name = "Alice";
                    int age = 30;
                    String message = String.format("My name is %s and I am %d years old.", name, age);
                    

                    小结

                    虽然C#和Java在运算符和表达式方面有很多相似之处,但C#提供了一些额外的特性,如空合并运算符、空条件运算符、表达式体成员等,这些可以让代码更加简洁和表达力更强。

                    作为一个从Java转向C#的开发者,你会发现这些额外的特性可以让你的代码更加优雅和易读。在实际编程中,合理利用这些特性可以提高代码质量和开发效率。

                    在接下来的学习中,我们将深入探讨C#的更多高级特性,如LINQ、异步编程等。这些概念将进一步展示C#相对于Java的独特优势。继续保持学习的热情,你会发现C#是一个功能丰富、表达力强的语言!

                    1.4 控制流语句

                    控制流语句是编程语言的基本构建块,用于控制程序的执行路径。C#和Java在这方面非常相似,但C#也有一些独特的特性。让我们深入了解C#的控制流语句,并与Java进行比较。

                    if-else 语句

                    C#和Java的if-else语句几乎完全相同:

                    int x = 10;
                    if (x > 5)
                    {
                        Console.WriteLine("x is greater than 5");
                    }
                    else if (x  
                    

                    C#特有的特性:

                    1. 可空类型的使用:
                    int? x = null;
                    if (x.HasValue)
                    {
                        Console.WriteLine($"x has a value: {x.Value}");
                    }
                    else
                    {
                        Console.WriteLine("x is null");
                    }
                    
                    1. 模式匹配(C# 7.0+):
                    object obj = "Hello";
                    if (obj is string s)
                    {
                        Console.WriteLine($"The string is: {s}");
                    }
                    

                    switch 语句

                    C#的switch语句比Java的更加灵活:

                    int day = 3;
                    switch (day)
                    {
                        case 1:
                            Console.WriteLine("Monday");
                            break;
                        case 2:
                            Console.WriteLine("Tuesday");
                            break;
                        case 3:
                        case 4:
                        case 5:
                            Console.WriteLine("Midweek");
                            break;
                        default:
                            Console.WriteLine("Weekend");
                            break;
                    }
                    

                    C#特有的特性:

                    1. 模式匹配(C# 7.0+):
                    object obj = 123;
                    switch (obj)
                    {
                        case int i when i > 100:
                            Console.WriteLine($"Large integer: {i}");
                            break;
                        case string s:
                            Console.WriteLine($"String value: {s}");
                            break;
                        case null:
                            Console.WriteLine("Null value");
                            break;
                        default:
                            Console.WriteLine("Unknown type");
                            break;
                    }
                    
                    1. switch 表达式(C# 8.0+):
                    string GetDayType(int day) => day switch
                    {
                        1 => "Monday",
                        2 => "Tuesday",
                        3 or 4 or 5 => "Midweek",
                        _ => "Weekend"
                    };
                    

                    循环语句

                    C#和Java的循环语句非常相似:

                    1. for循环:
                    for (int i = 0; i  
                    
                    1. while 循环:
                    int i = 0;
                    while (i  
                    
                    1. do-while 循环:
                    int i = 0;
                    do
                    {
                        Console.WriteLine(i);
                        i++;
                    } while (i  
                    
                    1. foreach 循环:
                    string[] fruits = { "apple", "banana", "cherry" };
                    foreach (string fruit in fruits)
                    {
                        Console.WriteLine(fruit);
                    }
                    

                    C#特有的特性:

                    1. LINQ与foreach的结合:
                    List numbers = new List { 1, 2, 3, 4, 5 };
                    foreach (var num in numbers.Where(n => n % 2 == 0))
                    {
                        Console.WriteLine(num);
                    }
                    

                    跳转语句

                    C#和Java都支持以下跳转语句:

                    1. break:跳出当前循环或switch语句
                    2. continue:跳过当前循环的剩余部分,开始下一次迭代
                    3. return:从方法中返回,并可选择返回一个值

                    C#特有的跳转语句:

                    1. goto:虽然不推荐使用,但C#保留了goto语句
                    int i = 0;
                    start:
                        if (i  
                    

                    异常处理

                    C#和Java的异常处理机制非常相似:

                    try
                    {
                        int result = 10 / 0;
                    }
                    catch (DivideByZeroException ex)
                    {
                        Console.WriteLine($"Division by zero error: {ex.Message}");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"An error occurred: {ex.Message}");
                    }
                    finally
                    {
                        Console.WriteLine("This always executes");
                    }
                    

                    C#特有的特性:

                    1. 异常过滤器(C# 6.0+):
                    try
                    {
                        // 可能抛出异常的代码
                    }
                    catch (Exception ex) when (ex.InnerException != null)
                    {
                        Console.WriteLine($"Inner exception: {ex.InnerException.Message}");
                    }
                    
                    1. using 语句(简化资源管理):
                    using (var file = new System.IO.StreamReader("file.txt"))
                    {
                        string content = file.ReadToEnd();
                        Console.WriteLine(content);
                    }
                    // file自动关闭
                    
                    1. using 声明(C# 8.0+):
                    using var file = new System.IO.StreamReader("file.txt");
                    string content = file.ReadToEnd();
                    Console.WriteLine(content);
                    // file 在作用域结束时自动关闭
                    

                    小结

                    虽然C#和Java在控制流语句方面有很多相似之处,但C#提供了一些额外的特性,如模式匹配、switch表达式、异常过滤器等,这些可以让代码更加简洁和表达力更强。

                    作为一个从Java转向C#的开发者,你会发现这些额外的特性可以让你的代码更加优雅和易读。特别是模式匹配和switch表达式,它们可以大大简化复杂的条件逻辑。

                    在实际编程中,合理利用这些特性可以提高代码质量和开发效率。例如,使用模式匹配可以使类型检查和转换更加简洁,使用switch表达式可以使复杂的条件判断更加清晰。

                    在接下来的学习中,我们将深入探讨C#的更多高级特性,如LINQ、异步编程等。这些概念将进一步展示C#相对于Java的独特优势。继续保持学习的热情,你会发现C#是一个功能丰富、表达力强的语言!

                    1.5 方法和参数

                    方法(在Java中称为函数)是编程中最基本的代码组织单元。C#和Java在方法定义和使用上有很多相似之处,但C#提供了一些额外的特性,使得方法定义和调用更加灵活。让我们深入探讨C#的方法和参数,并与Java进行比较。

                    方法定义

                    C#和Java的基本方法定义非常相似:

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

                    Java中的等效代码:

                    public int add(int a, int b) {
                        return a + b;
                    }
                    

                    主要区别:

                    1. C#方法名通常使用PascalCase,而Java使用camelCase。
                    2. C#支持方法重载,Java也支持。

                    参数传递

                    C#和Java都支持值传递和引用传递,但C#提供了更多选项:

                    1. 值参数(默认):
                    public void IncrementValue(int x)
                    {
                        x++; // 不影响原始值
                    }
                    
                    1. 引用参数(ref 关键字):
                    public void IncrementRef(ref int x)
                    {
                        x++; // 修改原始值
                    }
                    // 调用
                    int num = 5;
                    IncrementRef(ref num);
                    Console.WriteLine(num); // 输出 6
                    

                    Java没有直接等效的引用参数,但可以通过包装类或数组实现类似效果。

                    1. 输出参数(out 关键字):
                    public bool TryParse(string s, out int result)
                    {
                        return int.TryParse(s, out result);
                    }
                    // 调用
                    if (TryParse("123", out int number))
                    {
                        Console.WriteLine($"Parsed number: {number}");
                    }
                    

                    Java没有直接等效的输出参数。

                    1. 参数数组(params 关键字):
                    public int Sum(params int[] numbers)
                    {
                        return numbers.Sum();
                    }
                    // 调用
                    int total = Sum(1, 2, 3, 4, 5);
                    

                    Java使用可变参数(varargs)实现类似功能:

                    public int sum(int... numbers) {
                        return Arrays.stream(numbers).sum();
                    }
                    

                    方法重载

                    C#和Java都支持方法重载,允许在同一个类中定义多个同名但参数列表不同的方法:

                    public class Calculator
                    {
                        public int Add(int a, int b)
                        {
                            return a + b;
                        }
                        public double Add(double a, double b)
                        {
                            return a + b;
                        }
                    }
                    

                    Java的方法重载与C#基本相同。

                    可选参数

                    C#支持可选参数,这在Java中直到最近才引入:

                    public void Greet(string name, string greeting = "Hello")
                    {
                        Console.WriteLine($"{greeting}, {name}!");
                    }
                    // 调用
                    Greet("Alice"); // 输出: Hello, Alice!
                    Greet("Bob", "Hi"); // 输出: Hi, Bob!
                    

                    在Java中,你通常需要使用方法重载来实现类似功能:

                    public void greet(String name) {
                        greet(name, "Hello");
                    }
                    public void greet(String name, String greeting) {
                        System.out.println(greeting + ", " + name + "!");
                    }
                    

                    命名参数

                    C#支持命名参数,可以提高代码的可读性:

                    public void CreateUser(string name, int age, bool isAdmin = false)
                    {
                        //方法实现
                    }
                    // 调用
                    CreateUser(name: "Alice", age: 30, isAdmin: true);
                    CreateUser(age: 25, name: "Bob"); // 可以改变参数顺序
                    

                    Java不支持命名参数,但可以使用建造者模式来实现类似的效果。

                    表达式体方法

                    C# 6.0引入了表达式体方法,可以使简单方法的定义更加简洁:

                    public int Add(int a, int b) => a + b;
                    public string GetFullName(string firstName, string lastName) => $"{firstName} {lastName}";
                    

                    Java不支持这种语法糖。

                    本地函数

                    C# 7.0引入了本地函数,允许在方法内定义函数:

                    public int Factorial(int n)
                    {
                        int LocalFactorial(int x)
                        {
                            return x 
                        using var client = new HttpClient();
                        return await client.GetStringAsync(url);
                    }
                    // 调用
                    string data = await FetchDataAsync("https://api.example.com");
                    
                        return CompletableFuture.supplyAsync(() - {
                            // 使用HttpClient获取数据
                            return "data";
                        });
                    }
                    // 调用
                    String data = fetchDataAsync("https://api.example.com").join();
                    

                    扩展方法

                    C#允许你为现有类型添加新方法,而不需要修改原始类型的定义:

                    public static class StringExtensions
                    {
                        public static bool IsNullOrEmpty(this string str)
                        {
                            return string.IsNullOrEmpty(str);
                        }
                    }
                    // 使用
                    string name = "Alice";
                    bool isEmpty = name.IsNullOrEmpty();
                    

                    Java不支持扩展方法,但可以使用静态工具类来实现类似功能。

                    泛型方法

                    C#和Java都支持泛型方法,允许你编写可以处理多种类型的方法:

                    public T Max(T a, T b) where T : IComparable
                    {
                        return a.CompareTo(b) > 0 ? a : b;
                    }
                    // 使用
                    int maxInt = Max(5, 10);
                    string maxString = Max("apple", "banana");
                    

                    Java的泛型方法语法略有不同:

                    public  T max(T a, T b) {
                        return a.compareTo(b) > 0 ? a : b;
                    }
                    

                    方法组合与函数式编程

                    C#对函数式编程有很好的支持,可以轻松组合和传递方法:

                    Func square = x => x * x;
                    Func addOne = x => x + 1;
                    Func squareThenAddOne = x => addOne(square(x));
                    int result = squareThenAddOne(5); // 26
                    

                    Java也支持函数式编程,但语法略有不同:

                    Function square = x -> x * x;
                    Function addOne = x -> x + 1;
                    Function squareThenAddOne = square.andThen(addOne);
                    int result = squareThenAddOne.apply(5); // 26
                    

                    小结

                    虽然C#和Java在方法和参数的基本概念上很相似,但C#提供了更多的特性和灵活性。C#的引用参数、输出参数、命名参数、可选参数等特性可以让方法定义和调用更加灵活和清晰。此外,C#的异步方法、扩展方法和表达式体方法等特性可以让代码更加简洁和易读。

                    作为一个从Java转向C#的开发者,你会发现这些额外的特性可以大大提高你的编程效率和代码质量。例如,命名参数和可选参数可以减少方法重载的需求,扩展方法可以让你更容易地扩展现有类型的功能,而async/await则可以大大简化异步编程的复杂性。

                    在实际编程中,合理利用这些特性可以让你的代码更加清晰、简洁和易于维护。例如,使用命名参数可以提高代码的可读性,使用扩展方法可以使你的代码更加模块化,而使用异步方法可以提高应用程序的响应性。

                    随着你对C#的深入学习,你会发现更多强大的特性和用法。保持学习和实践的热情,你将能够充分利用C#的强大功能,成为一个高效的.NET开发者!

                    1.6 类和对象

                    类和对象是面向对象编程的核心概念,C#和Java在这方面有很多相似之处,但C#提供了一些额外的特性和语法糖,使得类的定义和使用更加灵活和简洁。让我们深入探讨C#的类和对象,并与Java进行比较。

                    类的定义

                    C#和Java的基本类定义非常相似:

                    public class Person
                    {
                        public string Name { get; set; }
                        public int Age { get; set; }
                        public void SayHello()
                        {
                            Console.WriteLine($"Hello, my name is {Name} and I'm {Age} years old.");
                        }
                    }
                    

                    Java中的等效代码:

                    public class Person {
                        private String name;
                        private int age;
                        public String getName() { return name; }
                        public void setName(String name) { this.name = name; }
                        public int getAge() { return age; }
                        public void setAge(int age) { this.age = age; }
                        public void sayHello() {
                            System.out.println("Hello, my name is " + name + " and I'm " + age + " years old.");
                        }
                    }
                    

                    主要区别:

                    1. C#使用属性(Properties)代替了Java的getter和setter方法。
                    2. C#的方法名通常使用PascalCase,而Java使用camelCase。

                    构造函数

                    C#和Java的构造函数定义类似:

                    public class Person
                    {
                        public string Name { get; set; }
                        public int Age { get; set; }
                        public Person(string name, int age)
                        {
                            Name = name;
                            Age = age;
                        }
                    }
                    

                    C#特有的特性:

                    1. 构造函数初始化器:
                    public class Employee : Person
                    {
                        public string Company { get; set; }
                        public Employee(string name, int age, string company) : base(name, age)
                        {
                            Company = company;
                        }
                    }
                    
                    1. 主构造函数(C# 9.0+):
                    public class Person(string name, int age)
                    {
                        public string Name { get; set; } = name;
                        public int Age { get; set; } = age;
                    }
                    

                    属性

                    C#的属性是一个强大的特性,可以替代Java中的getter和setter方法:

                    public class Person
                    {
                        private string name;
                        public string Name
                        {
                            get { return name; }
                            set { name = value; }
                        }
                        // 自动实现的属性
                        public int Age { get; set; }
                        // 只读属性
                        public bool IsAdult => Age >= 18;
                    }
                    

                    C# 6.0+引入了更简洁的属性语法:

                    public class Person
                    {
                        public string Name { get; set; } = "John Doe";
                        
                        public int Age { get; set; }
                        
                        public bool IsAdult => Age >= 18;
                    }
                    

                    静态成员

                    C#和Java都支持静态成员:

                    public class MathHelper
                    {
                        public static double PI = 3.14159;
                        public static int Add(int a, int b)
                        {
                            return a + b;
                        }
                    }
                    // 使用
                    double pi = MathHelper.PI;
                    int sum = MathHelper.Add(5, 3);
                    

                    继承

                    C#和Java的继承语法略有不同:

                    public class Animal
                    {
                        public virtual void MakeSound()
                        {
                            Console.WriteLine("The animal makes a sound");
                        }
                    }
                    public class Dog : Animal
                    {
                        public override void MakeSound()
                        {
                            Console.WriteLine("The dog barks");
                        }
                    }
                    

                    Java中的等效代码:

                    public class Animal {
                        public void makeSound() {
                            System.out.println("The animal makes a sound");
                        }
                    }
                    public class Dog extends Animal {
                        @Override
                        public void makeSound() {
                            System.out.println("The dog barks");
                        }
                    }
                    

                    主要区别:

                    1. C#使用冒号(:)表示继承,Java使用extends关键字。
                    2. C#需要使用virtual和override关键字来实现方法重写,Java只需要使用@Override注解。

                    接口

                    C#和Java的接口定义类似,但C#允许接口包含默认实现(C# 8.0+):

                    public interface IAnimal
                    {
                        void MakeSound();
                        void Move() => Console.WriteLine("The animal moves");
                    }
                    public class Dog : IAnimal
                    {
                        public void MakeSound()
                        {
                            Console.WriteLine("The dog barks");
                        }
                        // Move方法使用接口的默认实现
                    }
                    

                    Java8+也支持接口默认方法:

                    public interface Animal {
                        void makeSound();
                        default void move() {
                            System.out.println("The animal moves");
                        }
                    }
                    

                    匿名类型

                    C#支持匿名类型,可以快速创建简单的对象:

                    var person = new { Name = "Alice", Age = 30 };
                    Console.WriteLine($"{person.Name} is {person.Age} years old");
                    

                    Java也支持匿名类,但主要用于创建接口或抽象类的匿名实现。

                    Record类型(C# 9.0+)

                    C# 9.0引入了Record类型,用于创建不可变的引用类型:

                    public record Person(string Name, int Age);
                    var alice = new Person("Alice", 30);
                    var bob = alice with { Name = "Bob" }; // 创建一个新记录,只修改Name
                    

                    Java 14+引入了类似的Record特性:

                    public record Person(String name, int age) {}
                    

                    对象初始化器

                    C#支持对象初始化器,可以在创建对象时直接设置属性:

                    var person = new Person
                    {
                        Name = "Alice",
                        Age = 30
                    };
                    

                    Java不直接支持这种语法,通常使用建造者模式来实现类似效果。

                    扩展方法

                    C#允许为现有类型添加新方法,而不需要修改原始类型:

                    public static class StringExtensions
                    {
                        public static bool IsNullOrEmpty(this string str)
                        {
                            return string.IsNullOrEmpty(str);
                        }
                    }
                    // 使用
                    string name = "Alice";
                    bool isEmpty = name.IsNullOrEmpty();
                    

                    Java不支持扩展方法,但可以使用静态工具类来实现类似功能,或者使用manifold 插件支持。

                    部分类(Partial Classes)

                    C#支持部分类,允许将一个类的定义分散到多个文件中:

                    // File1.cs
                    public partial class MyClass
                    {
                        public void Method1() { }
                    }
                    // File2.cs
                    public partial class MyClass
                    {
                        public void Method2() { }
                    }
                    

                    Java不支持部分类的概念。

                    索引器(Indexers)

                    C#支持索引器,允许类像数组一样通过索引访问:

                    public class StringCollection
                    {
                        private List items = new List();
                        public string this[int index]
                        {
                            get { return items[index]; }
                            set { items[index] = value; }
                        }
                    }
                    // 使用
                    var collection = new StringCollection();
                    collection[0] = "Hello";
                    Console.WriteLine(collection[0]); // 输出: Hello
                    

                    Java没有直接等效的特性,通常需要定义专门的get和set方法。

                    运算符重载

                    C#允许为自定义类型定义运算符的行为:

                    public struct Complex
                    {
                        public double Real { get; set; }
                        public double Imaginary { get; set; }
                        public static Complex operator +(Complex c1, Complex c2)
                        {
                            return new Complex 
                            { 
                                Real = c1.Real + c2.Real,Imaginary = c1.Imaginary + c2.Imaginary
                            };
                        }
                    }
                    // 使用
                    var c1 = new Complex { Real = 1, Imaginary = 2 };
                    var c2 = new Complex { Real = 3, Imaginary = 4 };
                    var result = c1 + c2;
                    

                    Java不支持运算符重载。

                    嵌套类型

                    C#和Java都支持嵌套类型,但C#的访问规则更加灵活:

                    public class OuterClass
                    {
                        private int outerField = 10;
                        public class InnerClass
                        {
                            public void AccessOuterField(OuterClass outer)
                            {
                                Console.WriteLine(outer.outerField);
                            }
                        }
                    }
                    

                    在C#中,嵌套类可以访问外部类的私有成员,而在Java中,内部类需要外部类的实例才能访问其私有成员。

                    密封类和方法

                    C#使用sealed关键字来防止类被继承或方法被重写:

                    public sealed class FinalClass
                    {
                        // 这个类不能被继承
                    }
                    public class BaseClass
                    {
                        public virtual void VirtualMethod() { }
                    }
                    public class DerivedClass : BaseClass
                    {
                        public sealed override void VirtualMethod() { }
                        // 这个方法不能在子类中被重写
                    }
                    

                    Java使用final关键字实现类似功能。

                    析构函数和终结器

                    C#支持析构函数(用于结构体)和终结器(用于类):

                    public class ResourceHolder
                    {
                        private IntPtr resource;
                        public ResourceHolder()
                        {
                            resource = AllocateResource();
                        }
                        ~ResourceHolder()
                        {
                            FreeResource(resource);
                        }
                        private IntPtr AllocateResource() { /*分配资源 */ }
                        private void FreeResource(IntPtr handle) { /* 释放资源 */ }
                    }
                    

                    Java不支持析构函数,但有类似的finalize()方法(虽然不推荐使用)。

                    属性访问器的可访问性

                    C#允许为属性的getter 和 setter 单独设置访问级别:

                    public class Person
                    {
                        public string Name { get; private set; }
                        public Person(string name)
                        {
                            Name = name;
                        }
                    }
                    

                    Java不支持这种细粒度的访问控制。

                    init only setters(C#9.0+)

                    C#9.0引入了init only setters,允许在对象初始化时设置属性值,而之后这些属性是不可变的:

                    var circle = new Circle { Radius = 5 };
                    var bigCircle = new Circle { Diameter = 20 };
                    public class Circle
                    {
                        private double _radius;
                        public double Radius
                        {
                            get => _radius;
                            init => _radius = value;
                        }
                        public double Diameter
                        {
                            get => 2 * _radius;
                            init => _radius = value / 2;
                        }
                    }
                    

                    Java没有直接等效的特性。

                    顶级语句(C# 9.0+)

                    从C# 9.0开始,可以在文件级别直接编写代码,而不需要显式的Main方法:

                    Console.WriteLine("Hello, World!");
                    

                    这个特性简化了小型程序和脚本的编写。Java仍然需要一个包含main方法的类。

                    模式匹配(C# 7.0+)

                    C#支持高级的模式匹配,可以在switch语句和is表达式中使用:

                    object obj = "Hello";
                    if (obj is string s && s.Length > 5)
                    {
                        Console.WriteLine($"It's a long string: {s}");
                    }
                    var result = obj switch
                    {
                        string s => $"It's a string: {s}",
                        int i => $"It's an int: {i}",
                        _ => "It's something else"
                    };
                    

                    Java支持有限形式的模式匹配(从Java 14开始),但不如C#灵活。

                    小结

                    C#提供了丰富的特性来定义和使用类和对象,许多这些特性在Java中是没有直接等价物的。这些特性不仅可以让代码更加简洁和表达力更强,还可以提高开发效率和代码质量。

                    作为一个从Java转向C#的开发者,你会发现这些额外的特性可以让你以新的方式思考和组织代码。例如,索引器可以让你的自定义类型像数组一样使用,运算符重载可以让你的类型更自然地参与数学运算,而模式匹配则可以简化复杂的类型检查和转换逻辑。

                    在实际编程中,合理利用这些特性可以大大提高代码的可读性和可维护性。例如,使用属性可以简化数据封装,使用记录类型可以简化不可变数据模型的创建,而使用模式匹配可以使复杂的条件逻辑更加清晰。

                    随着你对C#的深入学习和实践,你会发现更多强大的特性和用法。保持学习和实践的热情,你将能够充分利用C#的强大功能,成为一个高效的.NET开发者!记住,编程语言只是工具,关键是要理解背后的概念和原理,并能够在实际问题中灵活应用这些知识。

                    1.7 继承和多态

                    继承和多态是面向对象编程的核心概念,C#和Java在这方面有许多相似之处,但C#提供了一些额外的特性和语法,使得继承和多态的实现更加灵活和强大。让我们深入探讨C#的继承和多态,并与Java进行比较。

                    基本继承

                    C#和Java的基本继承语法略有不同:

                    C#:

                    public class Animal
                    {
                        public string Name { get; set; }
                        public virtual void MakeSound()
                        {
                            Console.WriteLine("The animal makes a sound");
                        }
                    }
                    public class Dog : Animal
                    {
                        public override void MakeSound()
                        {
                            Console.WriteLine("The dog barks");
                        }
                    }
                    

                    Java:

                    public class Animal {
                        private String name;
                        public String getName() { return name; }
                        public void setName(String name) { this.name = name; }
                        
                        public void makeSound() {
                            System.out.println("The animal makes a sound");
                        }
                    }
                    public class Dog extends Animal {
                        @Override
                        public void makeSound() {
                            System.out.println("The dog barks");
                        }
                    }
                    

                    主要区别:

                    1. C#使用冒号(:)表示继承,Java使用extends关键字。
                    2. C#需要使用virtual和override关键字来实现方法重写,Java只需要使用@Override注解。
                    3. C#默认使用属性(Properties)而不是getter和setter方法。

                    构造函数和继承

                    在C#中,派生类的构造函数可以显式调用基类的构造函数:

                    public class Animal
                    {
                        public string Name { get; set; }
                        public Animal(string name)
                        {
                            Name = name;
                        }
                    }
                    public class Dog : Animal
                    {
                        public string Breed { get; set; }
                        public Dog(string name, string breed) : base(name)
                        {
                            Breed = breed;
                        }
                    }
                    

                    Java中的等效代码:

                    public class Animal {
                        private String name;
                        public Animal(String name) {
                            this.name = name;
                        }
                    }
                    public class Dog extends Animal {
                        private String breed;
                        public Dog(String name, String breed) {
                            super(name);
                            this.breed = breed;
                        }
                    }
                    

                    密封类和方法

                    C#使用sealed关键字来防止类被继承或方法被重写:

                    public sealed class FinalClass
                    {
                        // 这个类不能被继承
                    }
                    public class BaseClass
                    {
                        public virtual void VirtualMethod() { }
                    }
                    public class DerivedClass : BaseClass
                    {
                        public sealed override void VirtualMethod() { }// 这个方法不能在子类中被重写
                    }
                    

                    Java使用final关键字实现类似功能:

                    public final class FinalClass {
                        // 这个类不能被继承
                    }
                    public class BaseClass {
                        public void virtualMethod() { }
                    }
                    public class DerivedClass extends BaseClass {
                        @Override
                        public final void virtualMethod() { }
                        // 这个方法不能在子类中被重写
                    }
                    

                    抽象类和方法

                    C#和Java都支持抽象类和方法:

                    C#:

                    public abstract class Shape
                    {
                        public abstract doubleCalculateArea();
                    }
                    public class Circle : Shape
                    {
                        public double Radius { get; set; }
                        public override double CalculateArea()
                        {
                            return Math.PI * Radius * Radius;
                        }
                    }
                    

                    Java:

                    public abstract class Shape {
                        public abstract double calculateArea();
                    }
                    public class Circle extends Shape {
                        private double radius;
                        public void setRadius(double radius) { this.radius = radius; }
                        @Override
                        public double calculateArea() {
                            return Math.PI * radius * radius;
                        }
                    }
                    

                    接口

                    C#和Java都支持接口,但C# 8.0+允许接口定义默认实现:

                    C#:

                    public interface IDrawable
                    {
                        void Draw();
                        void Erase() => Console.WriteLine("Default erase behavior");
                    }
                    public class Square : IDrawable
                    {
                        public void Draw()
                        {
                            Console.WriteLine("Drawing a square");
                        }// Erase方法使用默认实现
                    }
                    

                    Java 8+也支持接口默认方法:

                    public interface Drawable {
                        void draw();
                        default void erase() {
                            System.out.println("Default erase behavior");
                        }
                    }
                    public class Square implements Drawable {
                        @Override
                        public void draw() {
                            System.out.println("Drawing a square");
                        }
                        // erase方法使用默认实现
                    }
                    

                    多重继承

                    C#和Java都不支持类的多重继承,但都允许一个类实现多个接口:

                    public interface IDrawable
                    {
                        void Draw();
                    }
                    public interface IResizable
                    {
                        void Resize(int width, int height);
                    }
                    public class Rectangle : IDrawable, IResizable
                    {
                        public void Draw()
                        {
                            Console.WriteLine("Drawing a rectangle");
                        }
                        public void Resize(int width, int height)
                        {
                            Console.WriteLine($"Resizing to {width}x{height}");
                        }
                    }
                    

                    泛型约束

                    C#支持泛型约束,可以限制泛型参数的类型:

                    public class GenericRepository where T : class, new()
                    {
                        public T CreateNew()
                        {
                            return new T();
                        }
                    }
                    

                    Java也支持泛型约束,但语法略有不同:

                    public class GenericRepository {
                        public T createNew() throws InstantiationException, IllegalAccessException {
                            return T.class.newInstance();
                        }
                    }
                    

                    协变和逆变

                    C#支持泛型接口和委托的协变和逆变:

                    public interface IEnumerable { /* ... */ }
                    public interface IComparer { /* ... */ }
                    IEnumerable strings = new List();
                    IEnumerable objects = strings; // 协变
                    IComparer objectComparer = /* ... */;
                    IComparer stringComparer = objectComparer; // 逆变
                    

                    Java也支持泛型的协变和逆变,但语法不同:

                    List strings = new ArrayList();
                    List
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]