导读:本期聚焦于小伙伴创作的《C#中new关键字有哪几种用法,分别适用于什么场景》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#中new关键字有哪几种用法,分别适用于什么场景》有用,将其分享出去将是对创作者最好的鼓励。

在C#开发过程中,new是一个多功能的关键字,根据使用场景的不同,它可以承担运算符、修饰符、泛型约束三种完全不同的角色,每种角色对应的语法规则和使用场景都有明确区分,很多初学者容易混淆这些用法,接下来就逐一展开说明。

C#中new关键字有哪几种用法,分别适用于什么场景

一、new作为运算符:创建对象与调用构造函数

这是new最常见的用法,用来在堆上分配内存、创建指定类型的实例,并且会自动调用对应类型的构造函数完成对象的初始化工作。使用new创建对象后,会返回该对象的引用,我们需要将这个引用赋值给对应类型的变量才能后续使用。

如果是值类型,使用new创建实例时也会调用对应的构造函数,不过值类型的内存分配通常在栈上,除非它被包含在引用类型中。下面通过代码示例展示new作为运算符的基本用法:

// 定义普通的引用类型类
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    
    // 自定义构造函数
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

// 定义值类型结构体
public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
    
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

class Program
{
    static void Main()
    {
        // new作为运算符创建引用类型实例
        Person person = new Person("张三", 25);
        Console.WriteLine($"姓名:{person.Name},年龄:{person.Age}");
        
        // new作为运算符创建值类型实例
        Point point = new Point(10, 20);
        Console.WriteLine($"坐标X:{point.X},坐标Y:{point.Y}");
        
        // 也可以不显式调用构造函数,使用默认无参构造
        Person defaultPerson = new Person();
        defaultPerson.Name = "李四";
        defaultPerson.Age = 30;
    }
}

需要注意,如果类型没有定义无参构造函数,就不能直接使用new 类型名()的方式创建实例,必须传入构造函数要求的参数。另外new运算符创建的对象,在不再被引用时会被垃圾回收器自动回收,不需要开发者手动释放内存。

二、new作为修饰符:隐藏基类可继承成员

当派生类定义了和基类同名的成员(包括方法、属性、字段、事件等)时,如果希望派生类的成员覆盖基类的对应成员,就需要在派生类的成员前加上new修饰符,这种用法叫做成员隐藏。如果不加new修饰符,编译器会给出警告,提示你如果是有意隐藏基类成员,需要添加new关键字。

new修饰符隐藏成员只会在编译阶段生效,运行时如果通过基类类型的引用访问该成员,仍然会调用基类的版本,这和override重写的多态特性有本质区别。下面通过代码示例对比new隐藏和override重写的差异:

// 基类
public class BaseClass
{
    // 基类的虚方法,可以被override重写
    public virtual void ShowMessage()
    {
        Console.WriteLine("这是基类的方法输出");
    }
    
    // 基类的普通方法,无法被override,只能被new隐藏
    public void BaseMethod()
    {
        Console.WriteLine("这是基类的普通方法");
    }
}

// 派生类
public class DerivedClass : BaseClass
{
    // 使用new修饰符隐藏基类的虚方法(这里没有用override,所以是隐藏不是重写)
    public new void ShowMessage()
    {
        Console.WriteLine("这是派生类隐藏后的方法输出");
    }
    
    // 使用new修饰符隐藏基类的普通方法
    public new void BaseMethod()
    {
        Console.WriteLine("这是派生类隐藏后的普通方法");
    }
}

class Program
{
    static void Main()
    {
        DerivedClass derived = new DerivedClass();
        // 直接通过派生类引用调用,访问的是派生类隐藏后的成员
        derived.ShowMessage(); // 输出:这是派生类隐藏后的方法输出
        derived.BaseMethod();  // 输出:这是派生类隐藏后的普通方法
        
        // 将派生类实例赋值给基类类型的引用
        BaseClass baseRef = derived;
        // 通过基类引用调用,访问的是基类的原始成员,不会触发派生类的隐藏版本
        baseRef.ShowMessage(); // 输出:这是基类的方法输出
        baseRef.BaseMethod();  // 输出:这是基类的普通方法
    }
}

使用new修饰符隐藏成员时,派生类成员的可访问性可以和基类成员不同,但通常建议保持一致的访问级别,避免逻辑混乱。如果需要在派生类中访问被隐藏的基类成员,可以通过base.成员名的方式调用。

三、new作为泛型约束:限定类型参数

在定义泛型类型或者泛型方法时,我们可以使用new()作为泛型约束,要求传入的类型参数必须有一个无参的公共构造函数。这样在泛型内部就可以使用new T()的方式创建类型参数的实例,否则编译器会报错,因为无法保证传入的类型支持无参构造。

new()约束必须放在所有泛型约束的最后面,不能和其他约束的顺序颠倒。下面通过代码示例展示new作为泛型约束的用法:

// 定义泛型类,添加new()约束,要求T必须有公共无参构造函数
public class ObjectFactory<T> where T : new()
{
    // 泛型方法,创建T类型的实例
    public T CreateInstance()
    {
        // 因为有了new()约束,这里可以合法使用new T()
        return new T();
    }
}

// 符合约束的类,有公共无参构造函数
public class Product
{
    public string ProductName { get; set; }
    
    // 公共无参构造函数
    public Product()
    {
        ProductName = "默认产品";
    }
}

// 不符合约束的类,没有公共无参构造函数
public class User
{
    public string UserName { get; set; }
    
    // 只有带参构造函数,没有无参构造函数
    public User(string name)
    {
        UserName = name;
    }
}

class Program
{
    static void Main()
    {
        // 正确:Product有公共无参构造函数,符合约束
        ObjectFactory<Product> productFactory = new ObjectFactory<Product>();
        Product product = productFactory.CreateInstance();
        Console.WriteLine(product.ProductName); // 输出:默认产品
        
        // 错误:User没有公共无参构造函数,无法满足new()约束,编译会报错
        // ObjectFactory<User> userFactory = new ObjectFactory<User>();
    }
}

需要注意,如果类型参数同时需要继承某个基类和满足new()约束,那么基类约束要写在前面,new()约束放在最后,例如where T : BaseClass, new()这样的写法才是正确的。

三种用法的核心区别总结

为了更清晰地区分new的三种用法,我们可以通过下面的表格做对比:

用法角色使用场景作用语法特征
运算符创建对象实例分配内存、调用构造函数、返回对象引用后面跟类型名和构造函数参数
修饰符派生类定义和基类同名的成员显式隐藏基类可继承成员,消除编译警告加在派生类成员声明的最前面
泛型约束定义泛型类型或泛型方法要求类型参数必须有公共无参构造函数写在where子句的最后,形式为new()

实际开发过程中,我们可以根据当前的使用场景判断new的角色,避免把不同用法的规则搞混。比如不要试图在泛型约束的场景下用new创建对象却忘记加new()约束,也不要在需要多态重写的时候错误使用new修饰符导致逻辑不符合预期。

C#语言new关键字运算符重载修饰符派生类修改时间:2026-06-02 21:26:09

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。