从`new()`到`.DoSomething()`:一篇讲透C#方法与构造函数的终极指南

一、构造函数(Constructor)

构造函数是一个特殊的方法,它的唯一使命就是在创建一个类的实例时执行初始化操作。它确保了对象在被使用之前,处于一个有效的、可预期的初始状态。

1. 构造函数的特征

  1. 名称必须与类名完全相同。
  2. 没有返回类型 ,甚至连void都不能写。
  3. 通常被声明为public,以便外部代码可以创建类的实例。

2. 默认构造函数

如果你在类中不定义任何构造函数,C#编译器会为你提供一个隐藏的、无参数的默认构造函数

csharp 复制代码
public class Robot
{
    public string Model;
}

// === 使用 ===
Robot r1 = new Robot(); // 编译器提供的默认构造函数被调用
// 此时 r1.Model 的值是其类型默认值,即 null

但只要你定义了任何一个 构造函数,编译器就不会再为你提供默认构造函数了。

3. 带参数的构造函数

它强制调用者在创建对象时,必须提供必要的初始数据。

csharp 复制代码
public class Robot
{
    public string Model { get; } // 设置为只读,体现其一旦设定就不应改变的特性
    public DateTime ProductionDate { get; }

    // 这是一个带参数的构造函数
    public Robot(string model)
    {
        // 验证输入
        if (string.IsNullOrWhiteSpace(model))
        {
            throw new ArgumentException("机器人型号不能为空。");
        }

        this.Model = model;
        this.ProductionDate = DateTime.UtcNow; // 记录生产日期

        Console.WriteLine($"型号为 {this.Model} 的机器人已生产!");
    }
}

// === 使用 ===
Robot terminator = new Robot("T-800"); // 必须提供型号
// Robot r2 = new Robot(); // 编译错误!因为定义了有参构造,默认的无参构造消失了。

4. 构造函数重载

一个类可以有多个构造函数,只要它们的参数列表不同即可。

参数列表不同可以是:

  • 类型不同
  • 数量不同
  • 顺序不同
csharp 复制代码
public class Robot
{
    public string Model { get; }
    public string Owner { get; set; }

    // 主构造函数,逻辑最完整
    public Robot(string model, string owner)
    {
        this.Model = model;
        this.Owner = owner;
    }

    // 重载1:只提供型号,主人默认为 "Cyberdyne Systems"
    public Robot(string model)
    {
        this.Model = model;
        this.Owner = "Cyberdyne Systems";
    }
}

5.构造函数链 (this关键字)

上面的重载代码有重复(this.Model = model;)。当初始化逻辑很复杂时,这种重复会导致维护困难。我们可以使用this关键字,让一个构造函数去调用同一个类中的另一个构造函数。

csharp 复制代码
public class Robot
{
    public string Model { get; }
    public string Owner { get; set; }

    // 主构造函数
    public Robot(string model, string owner)
    {
        this.Model = model;
        this.Owner = owner;
    }

    // 使用 : this(model, "Cyberdyne Systems")
    // 表示在执行这个构造函数的函数体之前,
    // 先去调用那个匹配签名的构造函数 Robot(string, string)
    public Robot(string model) : this(model, "Cyberdyne Systems")
    {
        // 这里可以留空,或者只写真正属于这个构造函数的特殊逻辑
        Console.WriteLine("一个无主机器人被生产...");
    }
}

6. 静态构造函数

普通构造函数在new对象时执行,用于初始化实例成员 。而静态构造函数在类首次被访问 时(如创建第一个实例、或调用静态成员)由.NET运行时自动调用,且只执行一次 ,用于初始化静态成员

csharp 复制代码
public class RobotFactory
{
    // 静态字段
    private static readonly string _factoryLocation;

    // 静态构造函数
    static RobotFactory()
    {
        // 用于初始化静态数据,比如从配置文件读取信息
        _factoryLocation = "California";
        Console.WriteLine("机器人总工厂启动!只启动一次。");
    }
}

// === 使用 ===
var f1 = new RobotFactory(); // 首次访问类,静态构造函数执行
var f2 = new RobotFactory(); // 不再执行静态构造函数

二、方法(Method

1. 方法的基本语法

csharp 复制代码
// 访问修饰符 返回类型 方法名(参数列表)
// {
//     方法体...
// }
public void Walk(int steps)
{
    Console.WriteLine($"机器人向前走了 {steps} 步。");
}
  • 返回类型 :如果方法执行完毕后需要返回一个结果,就指定其类型(int, string, bool等)。如果不需要,就使用void
  • 参数列表:定义了调用该方法时需要传入的数据。

2. 方法重载

与构造函数一样,方法也可以被重载。只要方法名相同,但参数列表不同即可。

csharp 复制代码
public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    // 重载:接受三个整数
    public int Add(int a, int b, int c)
    {
        return a + b + c;
    }

    // 重载:接受两个双精度浮点数
    public double Add(double a, double b)
    {
        return a + b;
    }
}

3.参数的特殊标识:out, ref, params

  1. out参数:返回多个值 out参数用于从方法中传出数据。它要求方法内部必须为其赋值。

    csharp 复制代码
    public bool TryParseCoordinates(string input, out int x, out int y)
    {
        x = 0; // 必须在方法内部初始化out参数
        y = 0;
        string[] parts = input.Split(',');
        if (parts.Length == 2 && int.TryParse(parts[0], out x) && int.TryParse(parts[1], out y))
        {
            return true;
        }
        return false;
    }
    
    // === 使用 ===
    string data = "10,20";
    if (TryParseCoordinates(data, out int lat, out int lon))
    {
        Console.WriteLine($"解析成功: X={lat}, Y={lon}");
    }
  2. ref参数:按引用传递 默认情况下,值类型(如int, struct)参数是按值传递 的(复制一份)。使用ref可以让方法直接操作原始变量

    csharp 复制代码
    public void Swap(ref int a, ref int b)
    {
        int temp = a;
        a = b;
        b = temp;
    }
    
    // === 使用 ===
    int x = 5, y = 10;
    Swap(ref x, ref y); // 调用和定义时都必须加ref
    Console.WriteLine($"x={x}, y={y}"); // 输出: x=10, y=5
  3. params参数:可变数量的参数 params允许你向方法传入任意数量的同类型参数。它必须是方法参数列表中的最后一个。

    csharp 复制代码
    public int Sum(params int[] numbers)
    {
        int total = 0;
        foreach (int num in numbers)
        {
            total += num;
        }
        return total;
    }
    
    // === 使用 ===
    int sum1 = Sum(1, 2, 3);
    int sum2 = Sum(5, 10, 15, 20, 25);

三、静态方法static

static关键字既可以修饰字段/属性,也可以修饰方法和构造函数。它划出了一条清晰的界线:属于对象实例 的,还是属于类本身的。

  • 实例方法(无static:

    • 属于某个具体的对象
    • 必须通过对象实例来调用。
    • 可以访问该对象的实例成员和静态成员。
  • 静态方法(有static:

    • 属于类本身,不属于任何具体对象。
    • 必须通过类名来调用。
    • 不能访问任何实例成员(因为它不知道你想操作哪个对象),只能访问其他静态成员。
csharp 复制代码
public class Robot
{
    public string Model { get; } // 实例成员
    public static int TotalRobotsProduced { get; private set; } // 静态成员

    public Robot(string model)
    {
        this.Model = model;
        TotalRobotsProduced++; // 实例构造函数可以访问静态成员
    }

    // 实例方法
    public void AnnounceModel()
    {
        // 可以访问实例成员Model和静态成员TotalRobotsProduced
        Console.WriteLine($"我是 {this.Model}。目前共生产了 {TotalRobotsProduced} 台机器人。");
    }

    // 静态方法
    public static void PrintFactoryInfo()
    {
        // 不能访问 this.Model (编译错误)
        Console.WriteLine($"这是一个机器人制造工厂。已生产 {TotalRobotsProduced} 台机器人。");
    }
}

// === 使用 ===
Robot.PrintFactoryInfo(); // 通过类名调用静态方法

Robot r1 = new Robot("R2-D2");
r1.AnnounceModel(); // 通过实例调用实例方法

Robot r2 = new Robot("C-3PO");
r2.AnnounceModel();

Robot.PrintFactoryInfo(); // 静态成员的值被所有实例共享和更新

结语

点个赞,关注我获取更多实用 C# 技术干货!如果觉得有用,记得收藏本文!

相关推荐
崔庆才丨静觅10 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606111 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了11 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅11 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅11 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
懒人咖12 小时前
缺料分析时携带用料清单的二开字段
c#·金蝶云星空
崔庆才丨静觅12 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment12 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅12 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊12 小时前
jwt介绍
前端