C# 泛型,泛型约束

泛型主要是为了解决代码的复用性

在泛型出现之前,如果需要用到不同的参数类型,但是方法体一样的时候,需要定义多个不同类型参数的方法,这样有太多的重复代码如下

       public static void ShowInt(int iParameter)
        {
            Console.WriteLine("类名称:"+typeof(TestFunctionClass).FullName+",参数类型:"+ iParameter.GetType().ToString() + ",参数Value:"+iParameter);
        }

        public static void ShowString(string sParameter)
        {
            Console.WriteLine("类名称:" + typeof(TestFunctionClass).FullName + ",参数类型:" + sParameter.GetType().ToString() + ",参数Value:" + sParameter);
        }

        public static void ShowDate(DateTime dParameter)
        {
            Console.WriteLine("类名称:" + typeof(TestFunctionClass).FullName + ",参数类型:" + dParameter.GetType().ToString() + ",参数Value:" + dParameter);
        }

 

在Main方法中进行调用

 Console.WriteLine("最开始展示不同类型参数的信息的时候,需要定义多个不同类型的方法,而方法内容是几乎一样的");
  TestFunctionClass.ShowInt(1);
  TestFunctionClass.ShowString("aaa");
  TestFunctionClass.ShowDate(DateTime.Now);
  Console.ReadLine();

输出结果

 

后来发现使用里氏替换原则,任何使用父类的地方可以使用子类来进行替换,于是有了下面这种写法(object是任何子类的父类)

 public static void ShowObject(object oParameter)
 {
     Console.WriteLine("类名称:" + typeof(TestFunctionClass).FullName + ",参数类型:" + oParameter.GetType().ToString() + ",参数Value:" + oParameter);
 }

在主方法中可以直接传递

 Console.WriteLine("后来发现通过里氏替换原则,任何父类出现的地方可以用子类来进行替换,可以节省大部分代码");
 TestFunctionClass.ShowObject(2);
 TestFunctionClass.ShowObject("bbb");
 TestFunctionClass.ShowObject(DateTime.Now);
 Console.WriteLine("但是这样出现一个问题,出现类类型之间的转换,发生了装箱操作,这样使性能得到了非常大的损耗,(值类型转换为引用类型)");

输出结果

 

这个时候出现了泛型,泛型是在定义的时候,不直接声明类型,直到调用的时候再去指定,延时声明的作用,避免了装箱操作,减少了性能损耗

        public static void ShowFanXing<T>(T tParameter)
        {
            Console.WriteLine("类名称:" + typeof(TestFunctionClass).FullName + ",参数类型:" + tParameter.GetType().ToString() + ",参数Value:" + tParameter);
        }

在主方法中调用

     TestFunctionClass.ShowFanXing<int>(3);
        TestFunctionClass.ShowFanXing<string>("ccc");
        TestFunctionClass.ShowFanXing<DateTime>(DateTime.Now);
        Console.WriteLine("使用泛型的时候性能和使用普通方法类似,远大于通过object(里氏替换原则)的性能(前提:如果发生了装箱操作的时候");

输出结果

 

这个时候,泛型的定义知道了,但是咱们发现好像泛型没有什么意义,在方法内只能使用的还是基类的一些属性和方法

这个时候需要引入一个东西,泛型约束,通过泛型约束,咱们可以在泛型方法(泛型类)中使用约束的属性和方法

先声明一些基础类

    public class Pepple
    {
        public int Age { get; set; }

        public string Name { get; set; }

        public string SayHi()
        {
            return "Hi,My Name is" + Name + ",My Age Is " + Age;
        }
    }

    public class Chinese : Pepple, ISiChuan
    {
        public string Dialect { get; set; }
        public string Food()
        {
            return "火锅";
        }
    }

    public class Japanese : Pepple, IGuangDao
    {
        public string ViewSakura()
        {
            return "美しい桜";
        }
    }

    public interface ISiChuan
    {
        string Dialect { get; set; }

        string Food();
    }

    public interface IGuangDao
    {
        string ViewSakura();
    }

泛型约束,方法

 public static void ShowPeople<T>(T tParameter) where T : Pepple
 {
     Console.WriteLine("名字:" + tParameter.Name + ",年龄:" + tParameter.Age);
     Console.WriteLine("说话:" + tParameter.SayHi());
 }

 

在主方法中可以进行调用

   Pepple people = new Pepple()
     {
         Age = 1,
         Name = "People Name"
     };
     //里氏替换原则
     Pepple chinese = new Chinese()
     {
          Age = 1,
          Name = "张三"
      };

      TestFunctionClass.ShowPeople<Pepple>(people);
      TestFunctionClass.ShowPeople<Pepple>(chinese);
      Console.WriteLine("这个时候还有一个问题,虽然用了泛型约束,可以使用约束类的属性和方法,但是,子类的一些特性还是不能访问,这个时候出现了接口约束");
      Console.ReadLine();

 输出结果

 

泛型接口约束

public static void ShowPeopleDetail<T>(T tParameter) where T : Pepple, ISiChuan
{
     Console.WriteLine("名字:" + tParameter.Name + ",年龄:" + tParameter.Age);
     Console.WriteLine("说话:" + tParameter.SayHi());
     Console.WriteLine("喜欢吃:" + tParameter.Food());
}

执行结果

 

结束

posted @ 2019-02-21 15:27  我不是你的狗  阅读(365)  评论(0编辑  收藏  举报