如何理解泛型中的new()约束

本文深入探讨了C#中泛型New约束的重要性,解释了为何在泛型类中实例化类型T时需要New约束,以及.NET如何通过反射机制实例化T对象。此外,还强调了在多个约束中New约束的位置规范。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:为什么需要New约束

假设有这样一个需求,它需要在定义一个泛型类时同时实例化T对象。有网友说了:"这还不简单,我立刻给你写一个",刷刷刷,得到以下的例子。

public class GenericTester<T>
{
    private T t;
    public GenericTester()
    {
        t = new T();
    }
}


不好意思,这位粗心的网友就是我。在这里,我犯了一个最大的惯性错误:主观的认为T永远为Object类型,无构造参数。那话又说回来了,这段不带New约束的错误代码会给调用客户带来什么问题呢?

假设客户在使用这个泛型类时传递了如下的T型参数:

GenericTester<User> t = new GenericTester<User>();

public class User
{
    public User(int userId,string userName)
    {
       ...
    }
}

这时,这段代码在编译时不能发现错误的,一旦当程序运行时就会抛出异常。


因此使用New的真正原因是:

客户调用这个泛型类时,强制编译器检查泛型类型是否为无参构造函数,防止客户传递多参构造函数类,避免运行时抛出异常,增加程序BUG。

 

二: .net实例化T对象机制原理

由于T在运行时才会知道具体的类型,在这里.net通过反射机制实例化T对象,楼上代码其实等同于:

public class GenericTester<T> where T : new()
{
    private T t;
    public GenericTester()
    {
        t = System.Activator.CreateInstance<T>();
    }
}

 

三:最后注意点
1.当一个泛型参数有多个约束时,New约束要放在最后面。

转载于:https://www.cnblogs.com/cstao110/p/3618643.html

<think>我们正在讨论C#参数约束。根据引用,我们可以总结如下: 1. 引用[1]展示了在成员函数中使用参数作为约束的例子,其中`U`必须继承自`T`。 2. 引用[2]说明类参数可以在类定义中用作约束,并且必须在尖括号中声明所有类参数。 3. 引用[3]提到C#7.3以后允许使用枚举类作为约束。 4. 引用[4]强调了约束的重要性,以避免运行时错误。 用户的问题:了解C#中参数约束的条件和用法。 回答结构: 1. 解释什么是约束及其作用。 2. 列出常见的约束并举例说明。 3. 说明多个约束的用法。 4. 提及一些特殊的约束(如枚举、委托等)以及版本支持情况。 5. 使用示例代码展示用法。 注意:所有代码示例中的参数和约束需要正确使用LaTeX格式(行内用$...$,独立成段用$$...$$)。但由于这里主要是代码块,我们使用代码块标记。 同时,按照要求生成相关问题。</think>### C# 参数约束详解 #### 一、约束的作用与语法 约束通过`where`关键字限制可传入的类参数,确保类安全性和功能可用性。基本语法: ```csharp class MyClass<T> where T : constraint_type { ... } ``` #### 二、主要约束及用法 1. **基类约束** 要求类参数必须继承指定基类: ```csharp class Repository<T> where T : EntityBase { public void Save(T entity) { ... } } ``` 2. **接口约束** 要求实现特定接口,支持多接口约束: ```csharp void Log<T>(T data) where T : ILogger, ISerializable { ... } ``` 3. **值类约束** (`struct`) 限制为值类(枚举、结构体等): ```csharp T CreateDefault<T>() where T : struct => default; ``` 4. **引用类约束** (`class`) 限制为引用类: ```csharp class Cache<T> where T : class { ... } ``` 5. **无参构造函数约束** (`new()`) 要求类必须有公共无参构造函数: ```csharp T CreateInstance<T>() where T : new() => new T(); ``` 6. **枚举约束** (C# 7.3+) 限制为枚举类: ```csharp string GetName<T>(T value) where T : Enum => Enum.GetName(typeof(T), value); ``` 7. **类参数约束** 约束参数之间的关系: ```csharp class Converter<T, U> where U : T { ... } // U必须继承T ``` #### 三、多约束组合 可叠加多个约束,顺序为:主约束 → 接口约束 → 构造函数约束: ```csharp T Process<T>(T obj) where T : BaseClass, IDisposable, new() { using (obj) { return new T(); } } ``` #### 四、特殊约束 - **非空约束** (C# 8.0+, `notnull`): `where T : notnull` 排除可空类 - **委托/元组约束** (C# 7.3+): `where T : Delegate` 或 `where T : ValueTuple` #### 五、使用场景 1. **类安全** 避免向方法传入不支持操作的类[^4]。 2. **访问特定成员** 如约束为`IComparable`后可调用`CompareTo()`方法。 3. **设计模式应用** 工厂模式中确保可实例化(`new()`约束)[^2]。 > 示例:带约束集合 ```csharp public class SmartList<T> where T : IEntity, new() { public void AddItem() => items.Add(new T()); private List<T> items = new(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值