泛型的参数简介和参数约束

本文详细介绍了C#中泛型的使用方法及其优势,包括泛型类型、泛型方法及泛型委托等概念,并重点讲解了如何通过类型参数约束来增强泛型的灵活性与安全性。

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

优点:
 
使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。
泛型最常见的用途是创建集合类。
可以创建自己的泛型接口,泛型类,泛型方法,泛型时间,泛型委托。
可以对泛型类进行约束已访问特定数据类型的方法
泛型类型可以应用于强大的反射技术


缺点:       

       泛型唯一的缺点是...它太容易学又太难理解,以至于绝大多数新手直接把泛型集合和泛型混为一谈,把避免装拆箱当做泛型的唯一目的...反而将泛型的本质都抛弃掉了...             

泛型类型参数简介

在定义泛型类型和泛型方法时,常用到泛型类型参数,泛型类型参数是在实例化泛型时指定类型的占位符。泛型类型参数放在“<>”内。

    泛型类型参数命名建议:

    (1)当泛型类型参数为单个字母时,建议用T表示。

    (1)当泛型类型参数用单词定义时,建议在单词前加T。

            static void PromptName<T>(T t) {}
            static void PromptName<Tuser>(Tuser user){}

泛型类型参数约束
 

约束说明

T:结构类型参数必须是值类型。 可以指定除 Nullable 以外的任何值类型。
T:类类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。
T:new()类型参数必须具有无参数的公共构造函数。 当与其他约束一起使用时,new() 约束必须最后指定。
T:<基类名>   类型参数必须是指定的基类或派生自指定的基类。
T:<接口名称>类型参数必须是指定的接口或实现指定的接口。 可以指定多个接口约束。 约束接口也可以是泛型的。
T:U为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。

 

(1)类型参数约束为结构(struct)

          类型参数必须是值类型

         static void Main(string[] args)
        {
            printType < int>(5);         //正确的写法
            printType<string>("5");    //错误的写法
        }       

                  static void printType<T>(T t)where T:struct
                   {       
                          Console.WriteLine($"类型:{t.GetType().ToString()} 值:{t}");
                   }

 

(2)类型参数约束为类(class)

          类型参数必须是值类型

         static void Main(string[] args)
        {
            printType < int>(5);         //错误的写法
            printType<string>("5");    //正确的写法
        }       

                  static void printType<T>(T t)where T:class
                   {       
                          Console.WriteLine($"类型:{t.GetType().ToString()} 值:{t}");
                   }

(3)类型参数约束为实例化(new())

类型参数必须是可以new的

               abstract class A
               {
                   private A()
                   {
                   }
                }

 

                 static void Main(string[] args)
                {
                 printType<A>(new A());  //错误              
                }       


                static void printType<T>(T t)where T:new()
                {     
                     Console.WriteLine($"类型:{t.GetType().ToString()} 值:{t}");
                }                                    

(4)类型参数约束为基类型(基类型)


        类型参数必须是指定的基类或派生自指定的基类。

    class A
      {
      }
      class B:A
      {
      }
      class C
      {
      }

             static void Main(string[] args)
             {
             printType<A>(new B());    //正确  
             printType<A>(new C());    //错误     
             }      


            static void printType<T>(T t)where T:A
            {      
                    Console.WriteLine($"类型:{t.GetType().ToString()} 值:{t}");
            }

 

 

(5)类型参数约束为接口类型(接口)

         类型参数必须是接口类型

    interface IA
      {
      }
      class B:IA
      {
      }
      class C
      {
      }

             static void Main(string[] args)
             {
             printType<A>(new B());    //正确  
             printType<A>(new C());    //错误     
             }      


            static void printType<T>(T t)where T:A
            {      
                    Console.WriteLine($"类型:{t.GetType().ToString()} 值:{t}");
            }


(6)类型参数约束为T:U(继承关系,或统一类型)

         class A
            {
            }
            class B:A
            {
            }
            class C:B
           {
               }
       

                 static void Main(string[] args)
            {
                 printType<B,A>(new B(),new C());      
             }    
  

     static void printType<T,U>(T t,U,u)where T:U
           {      
               Console.WriteLine($"类型:{t.GetType().ToString()} 值:{t}");
             }




获取泛型方法的类型
   
static void Main(string[] args)
            {
                 printType<B,A>(new B(),new C());      
             }    
  

     static T printType<T,U>(T t,U,u)where T:U //当你不清楚这个方法的返回值是什么,就可以那T代替。
           {      
               Console.WriteLine($"类型:{t.GetType().ToString()} 值:{t}");
return default(T); //当执行到里面的方法时
default(T)就会得到它的类型
            }


 

 

 

 

 

 

转载于:https://www.cnblogs.com/ljknlb/p/6632612.html

### 接口方法中的约束 在 C# 中,可以对接口的方法使用参数,并通过 `where` 关键字来施加约束。这使得能够限定传入类的特性,从而增强代码的安全性灵活性。 #### 定义带约束接口方法 下面是一个带有参数约束的例子: ```csharp public interface IGenericInterface<T> { void ProcessItem<U>(U item) where U : T; } ``` 在此例子中,任何实现了 `IGenericInterface<T>` 的类,在调用 `ProcessItem<U>()` 方法时,所提供的类 `U` 必须继承自或实现由 `T` 所代表的类[^1]。 #### 复杂约束的应用 还可以应用更复杂的约束组合,比如新对象创建的能力、基类限制以及特定接口的支持等: ```csharp public interface IDataProcessor<T> { void HandleData<U>(U data) where U : class, new(), IDisposable, T; } ``` 这段代码表示当调用 `HandleData<U>()` 时,类 `U` 不仅要遵循 `T` 类的要求,还必须是可以作为引用类(`class`)使用的、拥有无参构造函数(`new()`)的并且实现了 `IDisposable` 接口的对象[^2]。 #### 实现与使用 对于上述定义好的接口,其实现如下所示: ```csharp public class DataHandler : IDataProcessor<IMyType> { public void HandleData<U>(U data) where U : class, new(), IDisposable, IMyType { // Method implementation here... } } ``` 此处假设存在一个名为 `IMyType` 的接口,则 `DataHandler` 就是该接口的一个具体实现者[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值