.NET编程01(泛型)

一:Object 类型:一切类型的父类,通过继承,子类拥有父类一切属性和行为;任何父类出现的地方,都可以用子类来代替;

用一个方法来完成多个方法做的事

/// <summary>
    /// 普通方法类
    /// </summary>
    public class CommonMethod
    {
        /// <summary>
        /// 打印个int值
        /// </summary>
        /// <param name="iParameter"></param>
        public static void ShowInt(int iParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod).Name, iParameter.GetType().Name, iParameter);
        }

/// <summary>
        /// 打印个string值
        /// </summary>
        /// <param name="sParameter"></param>
        public static void ShowString(string sParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod).Name, sParameter.GetType().Name, sParameter);
        }

/// <summary>
        /// 打印个object值
        /// </summary>
        /// <param name="oParameter"></param>
        public static void ShowObject(object oParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod), oParameter.GetType().Name, oParameter);

}

Typeof():用来获取某个类型

缺点:

第一:object是应用类型的,所以把值类型的参数传入ShowObject()方法时,就会存在装箱和拆箱,影响性能

第二:传入参数里面的属性值无法被访问到

第三:涉及到类型安全的问题

二:泛型(不属于语法糖,是ClR升级后才支持的语法)

用途:对于不同类型的参数,具有相同行为的时候,希望代码能重用起来,这时候使用泛型

原理: /// 延迟申明:申明方法的时候并没有指定参数类型(实际存在两个参数:T是类型参数,oParameter是真实参数),而是等到使用的时候在指定

   /// 延迟思想:推迟一切可以推迟的

     /// 编译的时候,类型参数编译为占位符,在程序真实运行的时候,JIT进行即时编译替换为真实类型

public class GenericMethod

{

  /// <summary>
        /// 第一:泛型方法(方法名字后面带上尖括号,类型参数),尖括号类可以是任何没定义的任何字母或者类型,不要写关键字,不要把定义好的类写在里面

/// </summary>
        /// <param name="oParameter"></param>
        public static void Show<T>(T oParameter)
        {
            Console.WriteLine("This is {0},parameter={2},type={1}",
                typeof(CommonMethod), oParameter.GetType().Name, oParameter);

}

}

class Program
    {
        static void Main(string[] args)
        {

    int iValue = 123;

object ovalue=new object();

    //第一:泛型方法调用

    GenericMethod.Show<int>(ivalue);

    GenericMethod.Show(ivalue);//不指定类型参数,编译器自动推算

    GenericMethod.Show<string>(ivalue);//此时报错,<类型参数>参数类型:(ivalue)的类型必须吻合

         GenericMethod.Show<object>(ovalue);

}

}

三:泛型类/接口

//泛型类

public class GenericClass<M,T,S>

{

public void Show(M m){}//可以作为参数

 public  T get(){}//可以作为返回值

}

//泛型接口

publuc interInface IStudy<T>

{

    T  Study(T t);

}

//泛型委托

public delegate T GetHandler<T>();

//普通类

public class Child

:GenericClass<M,T,S>//报错普通类不能直接继承泛型类

     :GenericClass<int,string,double>//指定类型参数后才可以继承

   :IStudy<T>//报错普通类不能直接实现泛型接口

   :IStudy<string>//指定类型后可以

{

  public string Study(string t){}

}

//泛型类

public class GenericChils<M,T>//等于申明了两个局部类型 M,T

  :GenericClass<M,T,String>//泛型类可以直接继承泛型类

   :IStudy<T>//T和M都可以或者指定一个特定类型,除此之外不行,泛型类可以直接实现泛型接口

{

  T IStudy<T>.Study(T t){}

}

四:泛型约束

public class People

{

  public int Id { get; set; }

  public string Name { get; set; }
        public void Hi(){ }

}

public class Chinese :People:ISports

{

   public void SayHi(){}

public void Pingpang(){}

}

public interface ISports
    {
        void Pingpang();
    }

public class Constraint

{

      ///基类约束

   /// 1: 基类约束,就可以访问基类的属性和方法
          /// 2:被调用时, 参数必须是基类/子类

    public static void Show<T>(T oParameter) where T:People{}

     //接口约束

   public static void ShowInterface<T>(T oParameter) where T:ISports{}

  ///接口+基类约束

   public static void ShowBasic<T>(T oParameter) where T:People,ISports{}

   public static T Get<T>()

        //where T:Class//应用了类型约束

        //where T:struce//值类型约束

        //where T:new()//无参数构造函数约束

  {

    T t=new T();

    return null;//应用类型默认值

    return default(T):值类型默认值

  }

}

  泛型方法的约束的调用:

People people = new People()

Chinese chinese = new Chinese()

Constraint.Show<People>(People p)

Constraint.Show(people )

Constraint.Show<Chinese >(Chinese p)

Constraint.Show(chinese )

Constraint.ShowInterface(people)

五:泛型的协变/逆变(out/in):只能放在接口或者委托的参数前面,类没有协变逆变

out 协变 convariant 修饰返回值

in 逆变  contravariant 修饰传入参数       IEnumerable<int>    Action<int>

第一:协变

定义两个普通类

public class Bird{public int ID{get;set;}}

public class Sparrow:Bird{public string Name{get;set;}}

List<Bird> b1list=new List<bird>();------编译正确

List<Bird> B2list=new List<Sparrow>();------编译错误,因为list<Bird>和List<Sparrow>不是父子关系,没有继承关系

但是实际工作中会有这种需要(用父类集合来接受子类的集合)

一般的写法:List<Bird> B3list=new List<Sparrow>().select(c=>(Bird)c).ToList();-----编译正确,类型进行了强转

简单的写法:IEnumerable<Bird> b1=new List<bird>();---------协变

           IEnumerable<Bird> b2=new List<Sparrow>();---------协变(实际上也存在类型的的转换,只不过是编译器来做,减少了代码量)

以上写法采用协变使用系统提供的IEnumerable<out T>

public interface IEnumerable<out T> : IEnumerable  ------ 系统对IEnumerable<out T>的定义

使用List来接受子类集合会报错是因为,系统本身本没有对list进行协变定义

public class List<T>:IList<T>,IEnumerable<T>..........----------- 系统对List<T>的定义 参数没有Out

原因:List出现在.net2.0版本,而IEnumerable<out T>出现在C#4.0版本,两个不是属于同一个时期出现

自定义协变接口

Public interface ICustomerListOut<out T>

{

   T Get();-----正确

  void Show(T t)----报错,T不能作为传入参数,只能是返回结果;

}

//类没有协变逆变

public class CustomerListOut<T>:ICustomerListOut<T>

{

    public T Get(){return default(T);}

}

使用:

ICustomerListOut<Bird> b=new CustomerListOut<Bird>();

ICustomerListOut<Bird> b=new CustomerListOut<Sparrow>();

第二:逆变

自定义逆变接口

Public interface ICustomerListOut<in T>

{

   //T Get();-----报错,T只能作为传入参数,不能是返回结果;

  void Show(T t)----正确

}

public class CustomerListOut<T>:ICustomerListOut<T>

{

    public void Show(T t){}

}

使用:

ICustomerListIn<Sparrow> customerList2 = new CustomerListIn<Sparrow>();
 ICustomerListIn<Sparrow> customerList1 = new CustomerListIn<Bird>();

第三:逆变+协变(实际工作中使用很少,一般使用系统很少自己定义,系统自带Func<in T,out Tresult>)

public interface IMyList<in inT, out outT>
    {
        void Show(inT t);
        outT Get();
        outT Do(inT t);
    }

public class MyList<T1, T2> : IMyList<T1, T2>
    {

public void Show(T1 t)
        {
            Console.WriteLine(t.GetType().Name);
        }

public T2 Get()
        {
            Console.WriteLine(typeof(T2).Name);
            return default(T2);
        }

public T2 Do(T1 t)
        {
            Console.WriteLine(t.GetType().Name);
            Console.WriteLine(typeof(T2).Name);
            return default(T2);
        }
    }

使用:

     IMyList<Sparrow, Bird> myList1 = new MyList<Sparrow, Bird>();
                IMyList<Sparrow, Bird> myList2 = new MyList<Sparrow, Sparrow>();//协变
                IMyList<Sparrow, Bird> myList3 = new MyList<Bird, Bird>();//逆变
                IMyList<Sparrow, Bird> myList4 = new MyList<Bird, Sparrow>();//协变+逆变

第六:泛型的缓存

一般采用字典缓存:定义一个静态属性

/// <summary>
    /// 字典缓存:静态属性常驻内存
    /// </summary>
    public class DictionaryCache
    {
        private static Dictionary<string, string> _TypeTimeDictionary = null;
        static DictionaryCache()
        {
            Console.WriteLine("This is DictionaryCache 静态构造函数");
            _TypeTimeDictionary = new Dictionary<string, string>();
        }
        public static string GetCache<T>()
        {
            Type type = typeof(T);
            if (!_TypeTimeDictionary.ContainsKey(type.Name))
            {
                _TypeTimeDictionary[type.Name] = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
            }
            return _TypeTimeDictionary[type.Name];
        }
    }

第二:泛型缓存

原理:利用泛型每次在运行时Jit即时编译生成不同的副本

使用场景:用来保存固定数据,适合不同类型,需要缓存一份数据的场景,

优点:效率高

缺点:不能清除被回收

 /// <summary>
    /// 每个不同的T,在运行的时候JIT都会生成一份不同的副本,用于保存不同的T
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class GenericCache<T>
    {
        static GenericCache()
        {
            Console.WriteLine("This is GenericCache 静态构造函数");
            _TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
        }

private static string _TypeTime = "";

public static string GetCache()
        {
            return _TypeTime;
        }
    }

调用:

for (int i = 0; i < 5; i++)
            {
                Console.WriteLine(GenericCache<int>.GetCache());
                Thread.Sleep(10);
                Console.WriteLine(GenericCache<long>.GetCache());

  }

时间: 2024-10-29 19:05:43

.NET编程01(泛型)的相关文章

【C++】 网络编程 01

趁着计算机网络这门课布置了课程设计,学习下网络编程. 系统:Ubuntu 14.01... 1. 关于Socket(套接字) 1.1 套接字是存在于运输层和应用层间的抽象层,通过它来区分不同应用程序进程间的网络通信和连接. 其主要包含3个参数:通信的目的IP地址.使用的传输层协议(TCP或UDP)和使用的端口号. 1.2 套接字的通信流程: 1.3 socket()函数: int socket(int domain, int type, int protocol); 其中: domain为创建的

shell编程01—shell基础

01.学习shell编程需要的知识储备 1.vi.vim编辑器的命令,vimrc设置 2.命令基础,100多个命令 3.基础.高端的网络服务,nfs,rsync,inotify,lanmp,sersync,sshkey批量分发管理 02.shell脚本概念 1.什么是shell shell是一个命令解释器,在操作系统的最外层,负责直接与用户对话,将用户的输入解释给操作系统,并输出操作系统各种各样的处理结果,输出到屏幕返回给用户.这种对话方式可与是交互式的(键盘输入命令,可以立即得到shell的回

链式编程:泛型实现的扩展方法类

序言 本文分享一个用链式编程思想和泛型实现的扩展方法类,用于减少代码量,并提供更为清晰的业务逻辑代码表达. 概念 链式编程:将多个业务逻辑(方法)通过“.”(点号)串联起来的一种代码风格,形似链条,故称链式编程.核心思想在于每个方法均返回自身实例. 泛型:可以理解为是一个类的“篮子“”,只要符合约束的类均可以放置在该“篮子”里面. 扩展方法:向现有类添加方法. 根据泛型和扩展方法的特点,泛型+扩展方法实现了向所有符合约束的“类”添加方法,可减少重复代码量. (.Net语言提供了这么优雅的特性,刚

Java下的框架编程(反射,泛型,元数据,CGLib,代码动态生成,AOP,动态语言嵌入)

Java 虽然没有动态语言般暴起,但仍然天连天,水接水的生出好多框架技术---反射(reflection),泛型(generics),元数据(annotation),proxies(proxy/cglib),代码动态生成(asm),AOP(aspectJ),动态语言嵌入(groovy/javascript/beanshell).面对着这些,我们像一夜暴富的农企,有点手足无措的样子. 反射是一种让框架能够根据 "以字符串形式存在的信息" 来调用对象的属性和函数的技术,是Java对C++最

解读经典《C#高级编程》泛型 页114-122.章4

前言 本章节开始讲解泛型..Net从2.0开始支持泛型,泛型不仅是C#的一部分,也与IL代码紧密集成.所以C#中泛型的实现非常优雅.相对于C#,Java是后期引入的泛型,受限于最初的设计架构,就实现的比较别扭,遭到不少人的吐槽,比如"类型擦除"问题.使用C#还是幸福的. 使用泛型最典型的应用,可能是List<T>了,从List<T>我们可以看到,使用泛型最明显的优点是: 将List的功能和包含类T的功能分开,功能各自实现.使得代码内聚性.复用性.灵活性都更好.

python-网络编程-01

我们常说的计算机网络通信,值得是两台,或者多台计算机间,进行数据传输. 从计算机网络发展至今,人们使用了很多协议,但是最常用的还是tcp/ip协议,实际上这是一组协议. 当然使用python做网络编程的时候,我们通常都会在tcp/ip协议上面编程.也就是我们不需要关心,tcp/ip层真正传输层协议 [1] socket 通常我们可以这么理解socket -->用来标识远程主机上面的某一个进程. 当我们的客户端请求,发送到服务器的网口上面去之后,操作系统让哪个进程去处理它呢? socket解决的就

iOS之走进精益编程01

Model类 .h #import <Foundation/Foundation.h> @interface Product : NSObject @property (nonatomic,assign) NSNumber *weight; @property (nonatomic,copy)   NSString *color; @end .m 无增加内容 viewcontroller.h @interface ColorSpec :NSObject @property (nonatomic

【人生苦短 Python当歌】——Python函数式编程01

对Python有一定了解的人应该知道,Python并不是一门函数式编程语言,而是一门支持多种范式的语言,这也使得在Python中也能实现函数式编程, 对于学习到Python函数式编程的朋友,在这里推荐大家看一本名字叫<Python函数式编程>(Functional Programming in Python)从这本书中你应该能收获不少: 怎么说呢,函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就把复杂的任务分解成简单的任务,这种就称为面向过程的程序设

C++ GUI Qt4编程(01)-1.1Hello Qt

1. 根据C++ GUI Qt4编程(第二版)整理2. 系统:centos7:  Qt版本:5.5.13. 程序:hello.cpp #include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel *label = new QLabel("Hello, Qt!"); label->show();