찾다
php教程php手册c#中的泛型

这篇文章主要来讲讲c#中的泛型,因为泛型在c#中有很重要的位置,对于写出高可读性,高性能的代码有着关键的作用。当我多次看到自己团队的代码中包含着大量的非泛型集合,隐式的装箱和拆箱操作时,我都会建议他们补一补泛型基

      这篇文章主要来讲讲c#中的泛型,因为泛型在c#中有很重要的位置,对于写出高可读性,高性能的代码有着关键的作用。当我多次看到自己团队的代码中包含着大量的非泛型集合,隐式的装箱和拆箱操作时,我都会建议他们补一补泛型基础。

     1,什么是泛型

    • 泛型是c#2中非常重要的一个新特性,它增强了代码的可读性,将大量的安全检查从执行期转移到编译期,从而提高代码的安全性和性能。从根本上来说,泛型实现了类型和方法的参数化。

     2,为什么要使用泛型,泛型解决了什么问题

我们先来看看下面的代码(代码只是为了演示泛型,没有实际的意义),看看有什么问题?   

<span style="color: #008080;"> 1</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> PRogram
</span><span style="color: #008080;"> 2</span> <span style="color: #000000;">    {
</span><span style="color: #008080;"> 3</span>         <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span><span style="color: #000000;">[] args)
</span><span style="color: #008080;"> 4</span> <span style="color: #000000;">        {
</span><span style="color: #008080;"> 5</span>             ArrayList array = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ArrayList();
</span><span style="color: #008080;"> 6</span>             array.Add(<span style="color: #800080;">1</span><span style="color: #000000;">);
</span><span style="color: #008080;"> 7</span>             array.Add(<span style="color: #800080;">2</span><span style="color: #000000;">);
</span><span style="color: #008080;"> 8</span>             array.Add(<span style="color: #800080;">3</span><span style="color: #000000;">);
</span><span style="color: #008080;"> 9</span>             ArrayList resultArray =<span style="color: #000000;"> NumberSqrt(array);
</span><span style="color: #008080;">10</span>             <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> item <span style="color: #0000ff;">in</span><span style="color: #000000;"> resultArray)
</span><span style="color: #008080;">11</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">12</span> <span style="color: #000000;">                Console.WriteLine(item);
</span><span style="color: #008080;">13</span> <span style="color: #000000;">            }
</span><span style="color: #008080;">14</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">15</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> ArrayList NumberSqrt(ArrayList array)
</span><span style="color: #008080;">16</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">17</span>             ArrayList sqrtArray = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ArrayList();
</span><span style="color: #008080;">18</span>             <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> item <span style="color: #0000ff;">in</span><span style="color: #000000;"> array)
</span><span style="color: #008080;">19</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">20</span>                 sqrtArray.Add(Math.Sqrt((<span style="color: #0000ff;">double</span>)(<span style="color: #0000ff;">int</span><span style="color: #000000;">)item));
</span><span style="color: #008080;">21</span> <span style="color: #000000;">            }
</span><span style="color: #008080;">22</span>             <span style="color: #0000ff;">return</span><span style="color: #000000;"> sqrtArray;
</span><span style="color: #008080;">23</span> 
<span style="color: #008080;">24</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">25</span>     }
View Code
    • 首先ArrayList是一个非泛型集合,它需要的参数是object,那么我如果往集合里面装配其它的类型,在编译时也无法判断错误(比如说我装配一个字符串进去,完全是可以编译成功的)。
    • 由于ArrayList需要的是一个object,那么在你将值类型装配到集合中时,会进行隐式装箱操作,在使用集合中的数据时,需要进行拆箱操作。从而影响应用程序的性能。(关于值类型装箱请参考c#中的引用类型和值类型)。
    • 代码可以可读性差,完全看不明白ArrayList应该装配什么类型。

下面来看看泛型是如何解决这些问题的:

<span style="color: #008080;"> 1</span>     <span style="color: #0000ff;">class</span><span style="color: #000000;"> Program
</span><span style="color: #008080;"> 2</span> <span style="color: #000000;">    {
</span><span style="color: #008080;"> 3</span>         <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span><span style="color: #000000;">[] args)
</span><span style="color: #008080;"> 4</span> <span style="color: #000000;">        {
</span><span style="color: #008080;"> 5</span>             Listdouble> array = <span style="color: #0000ff;">new</span> Listdouble><span style="color: #000000;">();
</span><span style="color: #008080;"> 6</span>             array.Add(<span style="color: #800080;">1</span><span style="color: #000000;">);
</span><span style="color: #008080;"> 7</span>             array.Add(<span style="color: #800080;">2</span><span style="color: #000000;">);
</span><span style="color: #008080;"> 8</span>             array.Add(<span style="color: #800080;">3</span><span style="color: #000000;">);
</span><span style="color: #008080;"> 9</span>             Listdouble> resultArray =<span style="color: #000000;"> NumberSqrt(array);
</span><span style="color: #008080;">10</span>             <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> item <span style="color: #0000ff;">in</span><span style="color: #000000;"> resultArray)
</span><span style="color: #008080;">11</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">12</span> <span style="color: #000000;">                Console.WriteLine(item);
</span><span style="color: #008080;">13</span> <span style="color: #000000;">            }
</span><span style="color: #008080;">14</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">15</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> Listdouble> NumberSqrt(Listdouble><span style="color: #000000;"> array)
</span><span style="color: #008080;">16</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">17</span>             Listdouble> sqrtArray = <span style="color: #0000ff;">new</span> Listdouble><span style="color: #000000;">();
</span><span style="color: #008080;">18</span>             <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> item <span style="color: #0000ff;">in</span><span style="color: #000000;"> array)
</span><span style="color: #008080;">19</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">20</span>                 sqrtArray.Add(Math.Sqrt((<span style="color: #0000ff;">double</span>)(<span style="color: #0000ff;">int</span><span style="color: #000000;">)item));
</span><span style="color: #008080;">21</span> <span style="color: #000000;">            }
</span><span style="color: #008080;">22</span>             <span style="color: #0000ff;">return</span><span style="color: #000000;"> sqrtArray;
</span><span style="color: #008080;">23</span> 
<span style="color: #008080;">24</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">25</span> 
<span style="color: #008080;">26</span>     }
View Code
    • 由于List只能装配double,所以当你装配其它的类型时编译器会报错,提高代码的安全性。
    • 由于List只能装配double类型时,这样的话就避免了编译器隐式的装箱和拆箱操作,提高应用程序的性能。
    • 一眼就可以看出集合需要装配的类型,提高代码的可读性。
    • NumberSqrt方法在这里没什么用去,如果你要写一个算法,把NumberSqrt改为泛型方法:NumberSqrt(比如说排序算法),可以实现算法重用。

     3,如何使用泛型:语法和规则

上面已经说了什么是泛型,以及为什么要用泛型,下面我们来聊聊如何使用泛型

    • 泛型的语法:泛型主要有泛型方法(例如:static void Swap(ref T lhs, ref T rhs)),泛型接口( 例如: public interface IEnumerable : IEnumerable),泛型委托( 例如: public delegate void Action(T obj);)
    • 在FCL中内建了许多泛型的接口定义(常用的接口都在System.Collections.Generic),为了使泛型能够正常的工作,微软的开发人员将会做如下工作,
      • 创建新的IL指令,使之能够识别类型参数。
      • 改变元数据的格式,使之能够识别泛型参数和泛型方法。
    • 开放类型和封闭类型:当为一个泛型类型没有指定实际的数据类型时,就称为开放类型,例如List,对于任何开放类型都不能创建该类型的实例,例如下面的代码在运行是将会报错未:经处理的异常:  System.ArgumentException: 无法创建 Consoleapplication2.Demo`1[T] 的实例,因为 Type.ContainsGenericParameters 为 True。
<span style="color: #008080;"> 1</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> Demo<t><span style="color: #000000;"> { }
</span><span style="color: #008080;"> 2</span>     <span style="color: #0000ff;">class</span><span style="color: #000000;"> Program
</span><span style="color: #008080;"> 3</span> <span style="color: #000000;">    {
</span><span style="color: #008080;"> 4</span>         <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span><span style="color: #000000;">[] args)
</span><span style="color: #008080;"> 5</span> <span style="color: #000000;">        {
</span><span style="color: #008080;"> 6</span>             <span style="color: #0000ff;">object</span> o = <span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #008080;"> 7</span>             Type t = <span style="color: #0000ff;">typeof</span>(Demo<span style="color: #000000;">);
</span><span style="color: #008080;"> 8</span>             o =<span style="color: #000000;"> Activator.CreateInstance(t);
</span><span style="color: #008080;"> 9</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">10</span>     }</t>
View Code

               如果为泛型类型的所有类型实参传递的都是实际数据类型,类型就称为封闭类型,CLR允许构造封闭类型的实例。

    • 泛型类型和继承:泛型类型只是一个特殊的类型,所以它可以从其他任何类型派生。比如List是从object派生的,那么List也是从object派生的。换句话说,类型实参的指定和继承层次结构没有任何关系-理解这一点,有助于你判断那些转型是否能够进行,哪些转型是不能进行的。
    • 编译器如何解决“代码爆炸”的问题:在使用泛型类型或者方法方法时,Clr获取IL代码,用指定的类型实参进行替换。如果Clr为每种不同的类型/方法组合都生成不同的本地代码,他可能会增大应用程序的工作集,从而影响性能。我们将这种现象称为”代码爆炸“。那么编译器又是如何解决这个问题的呢?编译器认为所有引用类型的实参是完全相同的,所以代码能够共享(为什么这么说呢?是因为所有引用类型的实参或者变量实际只是指向堆上的对象的指针,而对象的指针全部是以相同的方式来操操纵的)。但是如果某个类型实参是值类型的话,CLR就得专门为那个值类型生成本地代码,这是值类型的大小不定。
    • 泛型接口:为什么要使用泛型接口呢?因为你每次试图使用一个非泛型接口来操作一个值类型时,都会发生装箱,从而失去编译时的类型安全性。所以CLR提供了对泛型接口的支持。下面来看一个例子:
      <span style="color: #008080;"> 1</span>    <span style="color: #008000;">//</span><span style="color: #008000;"> 摘要:
      </span><span style="color: #008080;"> 2</span>     <span style="color: #008000;">//</span><span style="color: #008000;">     支持在泛型集合上进行简单迭代。
      </span><span style="color: #008080;"> 3</span>     <span style="color: #008000;">//</span>
      <span style="color: #008080;"> 4</span>     <span style="color: #008000;">//</span><span style="color: #008000;"> 类型参数:
      </span><span style="color: #008080;"> 5</span>     <span style="color: #008000;">//</span><span style="color: #008000;">   T:
      </span><span style="color: #008080;"> 6</span>     <span style="color: #008000;">//</span><span style="color: #008000;">     要枚举的对象的类型。</span>
      <span style="color: #008080;"> 7</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">interface</span> IEnumeratorout T><span style="color: #000000;"> : IDisposable, IEnumerator
      </span><span style="color: #008080;"> 8</span> <span style="color: #000000;">    {
      </span><span style="color: #008080;"> 9</span>         <span style="color: #008000;">//</span><span style="color: #008000;"> 摘要:
      </span><span style="color: #008080;">10</span>         <span style="color: #008000;">//</span><span style="color: #008000;">     获取集合中位于枚举数当前位置的元素。
      </span><span style="color: #008080;">11</span>         <span style="color: #008000;">//</span>
      <span style="color: #008080;">12</span>         <span style="color: #008000;">//</span><span style="color: #008000;"> 返回结果:
      </span><span style="color: #008080;">13</span>         <span style="color: #008000;">//</span><span style="color: #008000;">     集合中位于枚举数当前位置的元素。</span>
      <span style="color: #008080;">14</span>         T Current { <span style="color: #0000ff;">get</span><span style="color: #000000;">; }
      </span><span style="color: #008080;">15</span>     }
      View Code
    • 泛型委托:CLR之所以要支持泛型委托,主要目的是保证任何类型的对象都能以一种类型安全的方式传给一个回调方法,并且保证了将一个值类型实例传递给一个回调方法时不执行任何装箱处理。
    • 泛型方法:定义泛型类,结构或者接口时,这些类型中定义的任何方法都可引用由类型指定的一个类型参数。类型参数可以作为方法的参数/返回值,或者作为方法内部的一个局部变量来使用。下面来看一个例子:
      <span style="color: #008080;"> 1</span>  <span style="color: #0000ff;">class</span><span style="color: #000000;"> Program
      </span><span style="color: #008080;"> 2</span> <span style="color: #000000;">    {
      </span><span style="color: #008080;"> 3</span>         <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span><span style="color: #000000;">[] args)
      </span><span style="color: #008080;"> 4</span> <span style="color: #000000;">        {
      </span><span style="color: #008080;"> 5</span>             MyClassstring> myclass = <span style="color: #0000ff;">new</span> MyClassstring><span style="color: #000000;">();
      </span><span style="color: #008080;"> 6</span>             myclass.ShowInfo(<span style="color: #800000;">"</span><span style="color: #800000;">myClass</span><span style="color: #800000;">"</span><span style="color: #000000;">);
      </span><span style="color: #008080;"> 7</span> <span style="color: #000000;">        }
      </span><span style="color: #008080;"> 8</span> <span style="color: #000000;">    }
      </span><span style="color: #008080;"> 9</span> 
      <span style="color: #008080;">10</span>     <span style="color: #0000ff;">class</span> MyClass<ta>
      <span style="color: #008080;">11</span> <span style="color: #000000;">    {
      </span><span style="color: #008080;">12</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> ShowInfo(Ta a)
      </span><span style="color: #008080;">13</span> <span style="color: #000000;">        {
      </span><span style="color: #008080;">14</span>             Type t = <span style="color: #0000ff;">typeof</span><span style="color: #000000;">(Ta);
      </span><span style="color: #008080;">15</span>             Console.WriteLine(t.FullName + <span style="color: #800000;">"</span><span style="color: #800000;">非泛型方法</span><span style="color: #800000;">"</span><span style="color: #000000;">);
      </span><span style="color: #008080;">16</span> <span style="color: #000000;">        }
      </span><span style="color: #008080;">17</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> ShowInfo<ta><span style="color: #000000;">(Ta a)
      </span><span style="color: #008080;">18</span> <span style="color: #000000;">        {
      </span><span style="color: #008080;">19</span>             Type t = <span style="color: #0000ff;">typeof</span><span style="color: #000000;">(Ta);
      </span><span style="color: #008080;">20</span>             Console.WriteLine(t.FullName + <span style="color: #800000;">"</span><span style="color: #800000;">泛型方法</span><span style="color: #800000;">"</span><span style="color: #000000;">);
      </span><span style="color: #008080;">21</span> <span style="color: #000000;">        }
      </span><span style="color: #008080;">22</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> ShowInfo<tb><span style="color: #000000;">(Ta a, Tb b)
      </span><span style="color: #008080;">23</span> <span style="color: #000000;">        {
      </span><span style="color: #008080;">24</span>             Type t = <span style="color: #0000ff;">typeof</span><span style="color: #000000;">(Tb);
      </span><span style="color: #008080;">25</span> <span style="color: #000000;">            Console.WriteLine(t.FullName);
      </span><span style="color: #008080;">26</span> <span style="color: #000000;">        }
      </span><span style="color: #008080;">27</span>     }</tb></ta></ta>
      View Code

       泛型方法的类型推断:c#语法中包含大量""符号,所以导致代码的可读性和可维护性降低了,所以为了改变这种情况,c#编译器支持在调用一个方法时进行类型推断。例如下面的代码:myclass.ShowInfo("myClass", myclass);会调用ShowInfo(string a, string b);

    • 可验证性和约束:编译器在编译泛型代码时,会对它进行分析,以确保代码适用于当前已有或将来可能定义的任何类型。请查看下面的方法:
      <span style="color: #008080;">1</span>      <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> Boolean MethodTakingAnyType<t><span style="color: #000000;">(T o) {
      </span><span style="color: #008080;">2</span>             T temp =<span style="color: #000000;"> o;
      </span><span style="color: #008080;">3</span> <span style="color: #000000;">            Console.WriteLine(o.ToString());
      </span><span style="color: #008080;">4</span>             Boolean b =<span style="color: #000000;"> temp.Equals(o);
      </span><span style="color: #008080;">5</span>             <span style="color: #0000ff;">return</span><span style="color: #000000;"> b;
      </span><span style="color: #008080;">6</span>         }</t>
      View Code

      看这个方法里面有一个临时变量temp。方法里面执行两次变量赋值和几次方法调用,无论T是值类型还是引用类型还是接口类型或者是委托类型这个方法都能工作。这个方法适用于当前存在的所以类型,也适用于将来可能定义的任何类型。比如你再看一下下面这个方法:

      <span style="color: #008080;">1</span>      <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> T MethodTakingAnyType<t><span style="color: #000000;">(T o1,T o2) {
      </span><span style="color: #008080;">2</span>             <span style="color: #0000ff;">if</span> (o1.CompareTo(o2) 0<span style="color: #000000;">)
      </span><span style="color: #008080;">3</span> <span style="color: #000000;">            {
      </span><span style="color: #008080;">4</span>                 <span style="color: #0000ff;">return</span><span style="color: #000000;"> o1;
      </span><span style="color: #008080;">5</span> <span style="color: #000000;">            }
      </span><span style="color: #008080;">6</span>             <span style="color: #0000ff;">else</span><span style="color: #000000;"> {
      </span><span style="color: #008080;">7</span>                 <span style="color: #0000ff;">return</span><span style="color: #000000;"> o2;
      </span><span style="color: #008080;">8</span> <span style="color: #000000;">            }
      </span><span style="color: #008080;">9</span>         }</t>
      View Code

      在编译时会报如下错误(error CS0117:"T"不包含"CompareTo"的定义),因为并不是所有的类型都提供了CompareTo方法。那么在什么情况下T应该是什么类型呢?幸好,编译器和CLR支持一个称为约束的机制,可利用它使泛型变得真正有用!

      • 约束的语法:请看下面这个方法名字后面的where
        <span style="color: #008080;">1</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> Boolean MethodTakingAnyType<t>(T o) <span style="color: #0000ff;">where</span> T : <span style="color: #0000ff;">struct</span>
        <span style="color: #008080;">2</span> <span style="color: #000000;">        {
        </span><span style="color: #008080;">3</span>             T temp =<span style="color: #000000;"> o;
        </span><span style="color: #008080;">4</span> <span style="color: #000000;">            Console.WriteLine(o.ToString());
        </span><span style="color: #008080;">5</span>             Boolean b =<span style="color: #000000;"> temp.Equals(o);
        </span><span style="color: #008080;">6</span>             <span style="color: #0000ff;">return</span><span style="color: #000000;"> b;
        </span><span style="color: #008080;">7</span>         }</t>
        View Code

        c#的where关键字告诉编译器,为T指定的任何类型都必须是值类型。所以当你为T指定其它类型时,编译器会报错,例如你指定为string类型时(MethodTakingAnyType("");)它会报错误    1    类型“string”必须是不可以为 null 值的类型才能用作泛型类型或方法

      • 主要约束:一个类型参数可以指定零个或一个主要约束(也就是第一个约束)。主要约束可以是一个引用类型,它标识了一个没有密封的类,不能指定以下特殊类型:System.Object;System.Array;System.Delegate;System.MulticastDelegate;System.ValueType;System.Enum;
      • 次要约束:一个类型参数可以指定零个或多个次要约束。次要约束是一个接口类型,指定一个接口类型约束时,是告诉编译器类型实参必须实现这个接口。还有一种次要约束称为类型参数约束,有时也称为裸类型约束,看下面的代码
        <span style="color: #008080;">1</span>  <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> Boolean MethodTakingAnyType<t tbase>(T o) <span style="color: #0000ff;">where</span><span style="color: #000000;"> T : TBase
        </span><span style="color: #008080;">2</span> <span style="color: #000000;">        {
        </span><span style="color: #008080;">3</span>             T temp =<span style="color: #000000;"> o;
        </span><span style="color: #008080;">4</span> <span style="color: #000000;">            Console.WriteLine(o.ToString());
        </span><span style="color: #008080;">5</span>             Boolean b =<span style="color: #000000;"> temp.Equals(o);
        </span><span style="color: #008080;">6</span>             <span style="color: #0000ff;">return</span><span style="color: #000000;"> b;
        </span><span style="color: #008080;">7</span>         }</t>
        View Code

        T类型参数由TBase类型单数约束,也就是说不管T为什么类型,都必须兼容于TBase指定的类型实参。

      • 构造器约束:一个类型参数可以指定零个或一个构造器约束。指定构造器约束相当于告诉编译器一个指定的类型实参必须要实现了公共无参构造器。请看下面的的代码:
        <span style="color: #008080;">1</span>       <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> Boolean MethodTakingAnyType<t tbase>(T o) <span style="color: #0000ff;">where</span> T : <span style="color: #0000ff;">new</span><span style="color: #000000;">()
        </span><span style="color: #008080;">2</span> <span style="color: #000000;">        {
        </span><span style="color: #008080;">3</span>             T temp =<span style="color: #000000;"> o;
        </span><span style="color: #008080;">4</span> <span style="color: #000000;">            Console.WriteLine(o.ToString());
        </span><span style="color: #008080;">5</span>             Boolean b =<span style="color: #000000;"> temp.Equals(o);
        </span><span style="color: #008080;">6</span>             <span style="color: #0000ff;">return</span><span style="color: #000000;"> b;
        </span><span style="color: #008080;">7</span>         }</t>
        View Code
      • 其它可验证性的问题:1,泛型类型变量的转型。下面的类型编译时出错,因为T可能为任何类型,无法保证能转型成功!
        <span style="color: #008080;">1</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> MethodTakingAnyType<t tbase><span style="color: #000000;">(T o)
        </span><span style="color: #008080;">2</span> <span style="color: #000000;">        {
        </span><span style="color: #008080;">3</span>             <span style="color: #0000ff;">int</span> x = (<span style="color: #0000ff;">int</span><span style="color: #000000;">)o;
        </span><span style="color: #008080;">4</span>             <span style="color: #0000ff;">string</span> s = (<span style="color: #0000ff;">string</span><span style="color: #000000;">)o;
        </span><span style="color: #008080;">5</span>         }</t>
        View Code

        2,将一个泛型类型变量设置为默认值:o = default(T);这样的话,不管T为值类型还是引用类型都可以成功,如果T为引用类型时就设置为null,如果T为值类型时将默认值设为0;

        3,将一个泛型类型变量与Null进行比较:使用==或者=!将一个泛型类型变量于null进行比较都是合法的。但是如果T为值类型时,o永远都不会为null查看下面的代码:
        <span style="color: #008080;">1</span>        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> MethodTakingAnyType<t tbase><span style="color: #000000;">(T o)
        </span><span style="color: #008080;">2</span> <span style="color: #000000;">        {
        </span><span style="color: #008080;">3</span>             <span style="color: #0000ff;">if</span> (o == <span style="color: #0000ff;">null</span><span style="color: #000000;">) { 
        </span><span style="color: #008080;">4</span>             <span style="color: #008000;">//</span><span style="color: #008000;">do something</span>
        <span style="color: #008080;">5</span> <span style="color: #000000;">            }
        </span><span style="color: #008080;">6</span>         }</t>
        View Code

        4,将两个泛型类型变量相互比较:如果T是值类型,下面的代码就是非法的。

        <span style="color: #008080;">1</span>    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> MethodTakingAnyType<t><span style="color: #000000;">(T o1,T o2)
        </span><span style="color: #008080;">2</span> <span style="color: #000000;">        {
        </span><span style="color: #008080;">3</span>             <span style="color: #0000ff;">if</span> (o1 ==<span style="color: #000000;"> o2) { 
        </span><span style="color: #008080;">4</span>             
        <span style="color: #008080;">5</span> <span style="color: #000000;">            }
        </span><span style="color: #008080;">6</span>         }</t>
        View Code

     4,泛型在使用过程的注意事项

    • 泛型不支持协变性
    • 缺乏操作符约束或者“数值”约束
    • 缺乏泛型属性,索引器和其它成员类型

 


성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

mPDF

mPDF

mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구