zoukankan      html  css  js  c++  java
  • c#之泛型

    默认值

    现在我们先新建一个实例,在这定义了一个泛型类Test<T>,泛型类中有一个GetModel方法返回的是一个T类型

    public class Test<T>
        {
            public T GetModle()
            {
                T model = default(T);
                return model;
            }
        }
    T model = default(T);

    通过default关键字,将null赋予引用类型,将0赋予值类型

    约束

    下面给出了一些泛型约束的条件

    image

    继承

    1.泛型类型可以实现一个泛型接口,也可以派生自一个泛型类

    2.派生类可以是泛型类或非泛型类

    定义一个抽象的泛型基类

    public abstract class Calc<T>
        {
            public abstract T Add(T x, T y);
            public abstract T Sub(T x, T y);
        }

    派生类中可以定义非泛型类

    class IntCalc:Calc<int>
        {
            public override int Add(int x, int y)
            {
                return x + y;
            }
            public override int Sub(int x, int y)
            {
                return x - y;
            }
        }

    协变和逆变

    感觉协变类似多态

    首先我们定义一个简单的类

    public class People
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public int Age { get; set; }
        }
    class Chinese:People
        {
            public string Hukou { get; set; }
        }
    People p = new Chinese();

    这样子我们就简单的通过继承并且实现了类型的隐式转换

    Chinese c = (Chinese)p;

    这是类型的强制转换

    在泛型接口中,我们是不是也可以做如下的假设呢,首先我们定义一个泛型接口

    interface IMyInterface<T>
    { 
    }

    如果上面的类型的隐式和强制转换都存在的话,下面的代码是可以编译通过的

    IMyInterface<People> p=new IMyInterface<Chinese>();
    IMyInterface<Chinese> c=(IMyInterface<Chinese>)p;

    但是在.net4.0(c#4.0之前)也就是在泛型接口中是没有所谓的上述的定义,所以在c#4.0后微软就有了协变和逆变的概念了

    协变:泛型接口从子类向父类的变化

    逆变:泛型接口父类向子类的变化

    条件:通过在泛型接口的声明中加入int和out来修饰泛型参数T

    协变和逆变的注意事项:

    1. 只有接口和委托支持协变和逆变(如Func<out TResult>,Action<in T>),类或泛型方法的类型参数都不支持协变和逆变。

    2. 协变和逆变只适用于引用类型,值类型不支持协变和逆变(因为可变性存在一个引用转换,而值类型变量存储的就是对象本身,而不是对象的引用),所以List<int>无法转化为Ienumerable<object>.

    3. 必须显示用in或out来标记类型参数。

    泛型方法

    泛型方法可以在非泛型类中定义

    一个简单的泛型方法的使用例子

    static void Swap<T>(ref T x, ref T y) {
                T temp;
                temp = x;
                x = y;
                y = temp;
            }
    int x = 4;
        int y = 5;
        Swap<int>(ref x,ref y);
        Console.WriteLine(string.Format("x的值{0},y的值{1}", x, y));

    在定义一个简单的例子

    public static decimal Accumulate<TAccount>(IEnumerable<TAccount> source) where TAccount : IAccount
           {
               decimal sum = 0;
               foreach (TAccount a in source) {
                   sum += a.Balance;
               }
               return sum;
           }

    泛型方法的重载

    public void Foo<T>(T obj)
           {
               Console.WriteLine("Foo<T>(T obj),obj type:{0}", obj.GetType().Name);
           }
           public void Foo(int x)
           {
               Console.WriteLine("Foo(int x)");
           }

    在编译期间,如果传递一个int类型,就选择带int参数的方法,对于其他类型,编译器会选择其他方法

  • 相关阅读:
    项目笔记三
    ASP.NET小收集<9>:HTML解析
    TSQL数据维护:更改表所有者
    [转贴]SQL2005:数据类型最大值
    TSQL存储过程:ROW_NUMBER()分页
    JS收集<7>:浏览器event兼容
    统计SQLServer2005表记录数
    ASP.NET小收集<8>:JS创建对象
    JS收集<8>:HTML控件的坐标
    MySql按指定天数进行分组数据统计分析 1
  • 原文地址:https://www.cnblogs.com/ilooking/p/4146163.html
Copyright © 2011-2022 走看看