在 C# 中,new 关键字有 三种主要用途,作为初级工程师,你需要掌握它们各自的场景和区别:


✅ 1. 创建对象实例(最常用)

这是 new 最常见的用法:在堆上分配内存并调用构造函数,创建类或结构体的实例

示例:

// 创建类的实例(引用类型)
Person person = new Person("Alice", 25);

// 创建结构体的实例(值类型)
Point p = new Point(10, 20);

// C# 9+ 支持目标类型推断(更简洁)
Person person2 = new("Bob", 30); // 编译器知道要创建 Person

💡 底层发生了什么?

  • 为对象分配内存(类在堆上,struct 在栈或内联)
  • 调用对应的构造函数初始化字段
  • 返回对该对象的引用(或值副本)

✅ 2. 隐藏基类成员(成员隐藏 / Shadowing)

在派生类中,用 new 修饰符可以隐藏(不是重写)基类中同名的成员

示例:

class Base
{
    public void Say() => Console.WriteLine("Base");
}

class Derived : Base
{
    public new void Say() => Console.WriteLine("Derived"); // 隐藏基类方法
}

调用效果:

Derived d = new Derived();
d.Say(); // 输出 "Derived"

Base b = d; // 向上转型
b.Say(); // 输出 "Base"!因为是隐藏,不是多态重写

⚠️ 注意:

  • 这不是多态!它只是“名字覆盖”,运行时根据变量类型决定调用哪个方法。
  • 如果不用 new,编译器会警告:“隐藏继承成员,请使用 new 显式隐藏”。
  • override 完全不同:override 是真正的重写,支持多态。

✅ 3. 泛型约束(where T : new()

在泛型中,new() 约束表示:类型参数 T 必须有一个公共的无参构造函数

示例:

public static T CreateInstance<T>() where T : new()
{
    return new T(); // 可以安全调用 new T()
}

// 使用
var list = CreateInstance<List<int>>(); // ✅ List<int> 有无参构造
var person = CreateInstance<Person>();  // ✅ 前提是 Person 有 public 无参构造

❌ 如果 T 没有无参构造函数(比如只有带参构造),编译会报错。


📌 三种用法对比表

用法 场景 示例
创建实例 实例化类或结构 new MyClass()
隐藏成员 派生类中隐藏基类同名成员 public new void Method()
泛型约束 要求泛型类型有无参构造 where T : new()

⚠️ 常见误区

❌ 误区1:new 总是分配在堆上

✅ 正解:

  • new Class() → 堆
  • new Struct() → 栈(或内联),但语法上仍用 new

❌ 误区2:new 隐藏 = override 重写

✅ 正解:

  • new编译时绑定(看变量类型)
  • override运行时多态(看实际对象类型)

❌ 误区3:所有类型都能 new()

✅ 正解:接口、抽象类不能直接 new(除非有具体实现)。


💡 初学者建议

  1. 日常最常用的是第 1 种:创建对象。
  2. 第 2 种(隐藏)尽量少用,容易造成混淆,优先考虑 virtual + override 实现多态。
  3. 第 3 种在写通用工具方法(如工厂、序列化)时很有用。

问题

在泛型类中如何创建类型T的新对象?

必须为类型T添加new约束,然后使用此类型的构造函数。

有多少种用法?

new运算符,修饰符,约束

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐