首先我们来看一下泛型的基本概念:
      最显著的一点就是它参数化了类型,把类型作为参数抽象出来,从而使我们在实际的运用当中能够更好的实现代码的重复利用,同时它提供了更强的类型安全,更高的效率,不过在约束方面,它只支持显示的约束,这样在灵活性方面就显得不是那么好了.我觉得它之所以能够提供更高的效率是因为泛型在实例化的时候采用了"on-demand"的模式,即按需实例化,发生在JIT(Just In Time)编译时.
      下面来看如何定义一个泛型类,很简单,你只需要意识到一点,在这里,类型已经被参数化了:
using System;
using System.Collections.Generic;
using System.Text;

namespace GenericTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //使用string,int来实例化Test<T,S>类
            Test<string, int> t = new Test<string, int>("SHY520",22);

//调用泛型类中的方法
            t.SetValue();
        }
    }

/** <summary>
    /// 定义一个泛型类,该类有两个类型参数,分别是T,S
    /// http://pw.cnblogs.com
    /// </summary>
    /// <typeparam name="T">类型参数</typeparam>
    /// <typeparam name="S">类型参数</typeparam>
    public class Test<T,S>
    {
        //泛型类的类型参数可用于类成员
        private T name;
        private S age;

public Test(T Name,S Age)
        {
            this.name = Name;
            this.age = Age;
        }

public void SetValue()
        {
            Console.WriteLine(name.ToString());
            Console.WriteLine(age.ToString());
        }
    }
}

上面的例子不是很恰当,目的是让初学泛型的你了解一下泛型的定义及实例化方法,如上,我们定义了一个泛型类,那么如何实现泛型类的继承呢?这里需要满足下面两点中的任何一点即可:
1、泛型类继承中,父类的类型参数已被实例化,这种情况下子类不一定必须是泛型类;
2、父类的类型参数没有被实例化,但来源于子类,也就是说父类和子类都是泛型类,并且二者有相同的类型参数;
    //如果这样写的话,显然会报找不到类型T,S的错误
    public class TestChild : Test<T, S> { }

//正确的写法应该是
    public class TestChild : Test<string, int>{ }

public class TestChild<T, S> : Test<T, S> { }

public class TestChild<T, S> : Test<String, int> { }

接着我们来看看泛型接口,其创建以及继承规则和上面说的泛型类是一样的,看下面的代码:
    public interface IList<T
    {
        T[] GetElements();
    } 
    public interface IDictionary<K,V>             
    {
        void Add(K key, V value); 
    }

// 泛型接口的类型参数要么已实例化
    // 要么来源于实现类声明的类型参数
    class List<T> : IList<T>, IDictionary<int, T
    {
        public T[] GetElements() { return null; }
        public void Add(int index, T value) 
        { 
        }
    }

再来看一下泛型委托,首先我们定义一个类型参数为T的委托,然后在类中利用委托调用方法:
using System;
using System.Collections.Generic;
using System.Text;

namespace GenericTest
{
    //定义一个委托,类型参数为T,返回值类型T
    //泛型委托支持在返回值和参数上应用类型参数
    delegate string GenericDelete<T>(T value);

class test
    {
        static string F(int i) { return "SHY520"; }
        static string G(string s) { return "SHY520"; }

static void Main(string[] args)
        {
            GenericDelete<string> G1 = G;
            GenericDelete<int> G2 = new GenericDelete<int>(F);
        }
    } 
}

我们再来看泛型方法,C#的泛型机制只支持在方法申明上包含类型参数,也即是泛型方法。特别注意的是,泛型不支持在除了方法以外的其他类/接口成员上使用类型参数,但这些成员可以被包含在泛型类型中,并且可以使用泛型类型的类型参数。还有一点需要说的就是,泛型方法可以在泛型类型中,也可以存在于非泛型类型中。下面我们分别看一下泛型类型的申明,调用,重载和覆盖。
using System;
using System.Collections.Generic;
using System.Text;

namespace GenericTest
{
    class GenericClass
    {
        //申明一个泛型方法
        public T getvalue<T>(T t)
        {
            return t;
        }

//调用泛型方法
        //注意:在调用泛型方法时,对泛型方法的类型参数实例化
        public int useMethod()
        {
            return this.getvalue<int>(10);
        }

//重载getvalue方法
        public int getvalue(int i)
        {
            return i;
        }
    }

//下面演示覆盖
    //要注意的是,泛型方法被覆盖时,约束被默认继承,不需要重新指定约束关系
    abstract class Parent
    {
        public abstract K TEST<K, V>(K k, V v) where K : V;

}

class Child : Parent
    {
        public override T TEST<T, S>(T t, S s)
        {
            return t;
        }
    }
}

最后我们来看一下泛型中的约束:
        C#中的泛型只支持显示的约束,因为这样才能保证C#所要求的类型安全,但显示的约束并非时必须的,如果不加约束,泛型类型参数将只能访问 System.Object类型中的公有方法。“显式约束”由where子句表达,可以指定“基类约束”,“接口约束”,“构造器约束”,“值类型/引用类型约束”共四种约束。下面的例子来源于李建忠老师的讲座PPT。
1、基类约束:
    class A { public void F1() {} } 
    class B { public void F2() {} } 
    class C<S,T
    where S: A // S继承自A 
    where T: B // T继承自B 
    { 
    // 可以在类型为S的变量上调用F1,
    // 可以在类型为T的变量上调用F2 
    }

2、接口约束
    interface IPrintable { void Print(); 
    }
    interface IComparable<T> { int CompareTo(T v);}
    interface IKeyProvider<T> { T GetKey(); }
    class Dictionary<K,V> 
    where K: IComparable<K> 
    where V: IPrintable, IKeyProvider<K> 
    { 
    // 可以在类型为K的变量上调用CompareTo, 
    // 可以在类型为V的变量上调用Print和GetKey 
    }

3、构造器约束
class A { public A() { } } 
class B { public B(int i) { } } 
class C<T
where T : new() 

//可以在其中使用T t=new T();  

C<A> c=new C<A>(); //可以,A有无参构造器
C<B> c=new C<B>(); //错误,B没有无参构造器

4、值/引用类型约束
public struct A {  } 
public class B {  } 
class C<T
where T : struct 

// T在这里面是一个值类型 

C<A> c=new C<A>(); //可以,A是一个值类型
C<B> c=new C<B>(); //错误,B是一个引用类型

default 关键字

泛型代码中的默认关键字(C# 编程指南)<!---->

<!--Content type: DocStudio. Transform: devdiv2mtps.xslt.-->

在泛型类和泛型方法中产生的一个问题是,在预先未知以下情况时,如何将默认值分配给参数化类型 T

T 是引用类型还是值类型。

如果 T 为值类型,则它是数值还是结构。

给定参数化类型 T 的一个变量 t,只有当 T 为引用类型时,语句 t = null 才有效;只有当 T 为数值类型而不是结构时,语句 t = 0 才能正常使用。解决方案是使用 default 关键字,此关键字对于引用类型会返回空,对于数值类型会返回零。对于结构,此关键字将返回初始化为零或空的每个结构成员,具体取决于这些结构是值类型还是引用类型。以下来自 GenericList<T> 类的示例显示了如何使用 default 关键字。有关更多信息

where 泛型类型约束 default 关键字相关推荐

  1. 长挺丑,Go 最新的泛型类型约束语法介绍

    近期我们在分享<3 件与 Go 开发者有关的大小事>时,里面有一部分有提到 Go 泛型的约束类型语法又又又变了. 在评论区里看到不少的读者朋友大呼泛型的新类型约束语法挺丑,不如原本的好.. ...

  2. java8中的default关键字

    点击上方蓝色字体,选择"设为星标" 优质文章,及时送达 把代码写优雅,把架构设计优雅是个值得持续追求的事情.有很多银弹,语法糖和套路可以完美解决代码的扩展性,优雅性.今天简单了解下 ...

  3. JDK 8 新特性 之 default关键字

    前言 Jdk1.8之前的接口中只声明方法,方法具体实现应在子类中进行. Jdk1.8打破了这样的用法:接口中可以实现具体的方法体,只需要加上关键字static或者default修饰即可. defaul ...

  4. C#2.0泛型中的变化: default 关键字

    今天回答别人问题的时候,才发现原先的T.default语法被取消了,使用了新的default关键字来实现这一功能.还好回复前动手试了一下,不然就...-_-b 下面详细说明一下.之所以会用到defau ...

  5. c# default 关键字

    default 关键字 default 关键字可在 switch 语句或泛型代码中使用. switch 语句:指定默认标签. 泛型代码:指定类型参数的默认值. 这对于引用类型为 null,对于值类型为 ...

  6. java中default关键字_Java 中的 default 关键字及代码示例

    本文通过代码示例介绍如何在 Java 中使用 default 关键字. 基本上,有 3 个地方可以使用 Java 中的 default 关键字: 在 switch case 语句中指定默认值 在 Ja ...

  7. 关于java8的default关键字浅薄理解

    如何让接口来实现具体的方法 起因 今天在看springboot 的时候 发现对springmvc进行配置的时候 自定义的类继承了一个接口 然后 直接重写了接口里面的方法????这啥操作 我还以为是自己 ...

  8. java中default关键字

    default关键字介绍 default是在java8中引入的关键字,也可称为Virtual extension methods--虚拟扩展方法. 它是指,在接口内部包含了一些默认的方法实现(也就是接 ...

  9. 41.什么是default关键字? default的作用是?

    什么是default关键字? default的作用是? <1>JDK1.8的新特性!!! <2>default关键字可以在接口中使用,用于修饰方法; <3>使用de ...

最新文章

  1. 注销凭证与自定义屏幕
  2. CSS之引入方式和选择器
  3. [机器学习] LR与SVM的异同
  4. 设置三个线程顺序打印数字问题(转载)
  5. frameset和iframe的区别
  6. python 链表操作 优化_python---单链表的常用操作
  7. Sqlserver:timestamp数据类型
  8. Java中的类型列表与类型ArrayList
  9. Clickhouse:分区和数值化优化实测
  10. DSP篇--C6701的COFF文件有效数据分析与提取
  11. 安装Ubuntu时:安装程序向硬盘复制文件时遇到错误
  12. 谷歌地图开发:地理编码和反地理编码
  13. Leetcode 1599. Maximum Profit of Operating a Centennial Wheel (python)
  14. 微信小程序的一级页面和二级页面设置
  15. 丁奇的MySQL实战45讲 学习笔记[链接]
  16. TOJ 3471.Happy XiaoXiao Guo
  17. 适用于自助设备的rk3568安卓主板配置详解
  18. DWCC2018基本网页设计注意要点、使用技巧
  19. lodash中difference、differenceBy、differenceWith有什么区别?
  20. 火狐OS手机操作系统

热门文章

  1. 信息学奥赛一本通 1037:计算2的幂 | OpenJudge NOI 1.3 20
  2. 信息学奥赛一本通(1238:一元三次方程求解)
  3. 信息学奥赛一本通(2027:【例4.13】三角形)
  4. 分治 —— 莫队算法 —— 普通莫队
  5. Network of Schools(POJ-1236)
  6. 信息学奥赛C++语言:for_求和2
  7. 25 FI配置-财务会计-定义冲销原因
  8. c++初学者如何学好基础?
  9. android 游戏引擎 排行_4月旗舰手机性能排行榜:小米10 Pro第四,OPPO Ace2第五
  10. ubuntu升级python_Ubuntu 系统下可以做什么?——拥抱自由和安静