c#基础5

 泛型 :
    允许我们延迟编写类或方法中的数据类型, 直到真正使用时确定类型的一种规范
    1.可以创建自己的泛型接口、泛型类、泛型方法、泛型集合 ,泛型事件和泛型委托
    2.泛型的格式:    结构<泛型的名称T> 在定义泛型时T通常用作变量类型名称。但实际上 T 可以用任何有效名称代替   
    3.泛型方法在定义是提供泛型的类型  在调用方法时 提供具体的延迟编写的类型  
    4.泛型无法直接使用运算符 比如 + -  <  > 等 但是能使用Object中的属性和方法

  public static void Test<T>(T a, T b) 
        { 
                string temp  = a.ToString();
                string temp1 = b.ToString();
             Console.WriteLine(temp1+temp);
        }
 
 
  public static void Test1<T,鸡>(T a, T b,鸡 c)
        {
            string temp = a.ToString();
            string temp1 = b.ToString();
            Console.WriteLine(c.GetType().ToString()); 
            Console.WriteLine(temp1 + temp);
        }

泛型类

C# 语言中泛型类的定义与泛型方法类似,是在泛型类的名称后面加上<T>,当然,也可以定

义多个类型,即“<T1,T2,・・・>”。

 class People<T, C> {
 
        private T _age;
        public T Age { get; set; }
        public T Eat(C a ,C b) {
            
            
            return _age;
        } 
    
    }
泛型接口
  interface Inter<T>
    {
        void show(T t);
    }
 
    //定义接口Inter的子类InterImpA,明确泛型类型为String (2)
    public class InterImpA : Inter<int>
    {
        //子类InterImpA重写方法show,指明参数类型为string
        public void show(int t)
        {
            Console.WriteLine(t);
        }
    }
    //定义接口Inter的子类InterImpB,直接声明           (1)
    public class InterImpB<T> : Inter<T>
    {
        public void show(T t)
        {
            Console.WriteLine(t);
        }
    }

 c#内置了    IComparable 接口用于在要比较的对象的类中实现,可以比较任意两个对象。

 public class Student : IComparable<Student> {
 
        int Age { get; set; }
          //定义比较方法,按照学生的年龄比较 
        public int CompareTo(Student other) {
 
            if (this.Age == other.Age)
            {
                return 1;
            }
            else if (this.Age < other.Age)
            {
                return 2;
            }
 
            else {
 
                return 3;
            }
        
        }
 
    }

2.泛型可以提供代码性能,避免了装箱和拆箱

泛型和Object类型的区别
 
值类型转换成引用类型。这个转换称为装箱。相反的过程称为拆箱
 
int number = 10;  
// 装箱  
object obj = number;  
// 拆箱  
number = (int) obj;
 
 
C# 中 Object 是一切类型的基类,可以用来表示所有类型
 
Object 类型
 
> 优点:
> 1. object类型可以用来引用任何类型的实例;
> 2. object类型可以存储任何类型的值;
> 3. 可以定义object类型的参数;
> 4. 可以把object作为返回类型。
 
> 缺点:
> 1. 会因为程序员没有记住使用的类型而出错,造成类型不兼容;
> 2. 值类型和引用类型的互化即装箱拆箱使系统性能下降
 
 
 
装箱(从值类型转换到引用类型)需要经历如下几个步骤:
int a =10
object ob = a;
 
    首先在堆上分配内存。这些内存主要用于存储值类型的数据。
    接着发生一次内存拷贝动作,将当前存储位置的值类型数据拷贝到堆上分配好的位置。
    最后返回对堆上的新存储位置的引用。
 
拆箱(从引用类型转换为值类型)的步骤则相反:
// 拆箱  
number = (int) obj;
    首先检查已装箱的值的类型兼容目标类型。
    接着发生一次内存拷贝动作,将堆中存储的值拷贝到栈上的值类型实例中。
    最后返回这个新的值。
 
 
频繁拆装箱导致性能问题
由于拆箱和装箱都会涉及到一次内存拷贝动作,因此频繁地进行拆装箱会大幅影响性能
 
 
  泛型和装箱拆箱 对比
  public void abTest(object a, object b) {
 
            Console.WriteLine(a.ToString());
            Console.WriteLine(b.ToString());
        }
        public void abTest(T a, T b)
        {
 
            Console.WriteLine(a.ToString());
            Console.WriteLine(b.ToString());
        }
 
 
 
 

3. 泛型中的数据约束可以指定泛型类型的范围

泛型约束总共有五种。
约束 	说明
T:结构 	类型参数必须是值类型
T:类 	类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。
T:new() 	类型参数必须具有无参数的公共构造函数。 当与其他约束一起使用时,new() 约束必须最后指定。
T:<基类名> 	类型参数必须是指定的基类或派生自指定的基类。
T:<接口名称> 	类型参数必须是指定的接口或实现指定的接口。 可以指定多个接口约束。 约束接口也可以是泛型的。
 
        where T : struct        //约束 T 必须是值类型  
        where K : class         //约束 K 必须是引用类型   
        where V : IFace<T>      //约束 V 必须实现 IFace 接口  
        where W : K             //约束 W 必须是 K 类型,或者是 K 类型的子类  
        where X : class, new()  //约束 X 必须是引用类型,并且有一个无参数的构造函数,当有多个约束时,new()必须写在最后  
where Y : MyClass2      //约束 Y 必须是 MyClass2 类型,或者继承于 MyClass2 类
 
 
 
 
    //例子:
static void Main(string[] args)
        {
   Test1<int,string, myAAAA, TestTotal,TestTotal1> test1 = new Test1<int, string, myAAAA, TestTotal, TestTotal1>();
            myAAAA myAAAA = new myAAAA();
            TestTotal testTotal = new TestTotal();
            TestTotal1 testTotal1 = new TestTotal1();
            test1.Test1Mothod(10, "123", myAAAA, testTotal, testTotal1);
 
}
  class  Test1<T,H,W,D,V> 
        where T : struct 
        where H : class
        where W : MyInterface<T>
        where D : TestTotal
        where V : class,new()
    {
        public void Test1Mothod(T a, H b,W c,D d,V e) { 
            
              
        }
    }
 
 
 
 
委托约束
枚举约束  后续再说

4.泛型成员因类型不确定,可能是类、结构体、字符、枚举……所以不能使用算术运算符、比较运算符等进行运算!
注意,可以使用赋值运算符。

5.泛型默认值问题 需要用   default()方法

 
之所以会用到default关键字,是因为需要在不知道类型参数为值类型还是引用类型的情况下,为对象实例赋初值。
 
引用类型会返回 null,对于数值类型会返回零。对于结构,此关键字将返回初始化为零或 null 的每个结构成员,具体取决于这些结构是值类型还是引用类型。对于可以为 null 的值类型,默认返回 System.Nullable<T>
 
 
 
///如果我们用int型来绑定泛型参数,那么T就是int型,
///那么注释的那一行就变成了 int t = null;显然这是无意义的。
///为了解决这一问题,引入了default关键字:
 
  TestDefault<int?> testDefault = new TestDefault<int?>();
  Console.WriteLine(testDefault.foo());
 
 class TestDefault<T>
    {
        public T foo()
        {
           // T t = null; //错误赋值方式 
            T t = default(T);
            return t;
        }
    }

在C#中ArrayList与List是常用的集合
ArrayList

ArrayList的优点:

    ArrayList大小是按照其中存储的数据来动态扩充与收缩的

    ArrayList 在声明对象时并不需要指定它的长度

    ArrayList可以很方便地进行数据的添加插入删除

   ArrayList 可以存储任意类型

 ArrayList aList = new ArrayList();
            //插入
            aList.Add(123);
            aList.Add("ABC");
            aList.Insert(1, 123 + "ABC"); //123 + "ABC" ->(隐式转换)"123ABC"
            //移除
            aList.RemoveAt(0); //索引处
            aList.Remove("ABC");

ArrayList的缺点:

    ArrayList在存储数据时使用object类型进行存储的

    ArrayList不是类型安全的,使用时很可能出现类型不匹配的错误
    就算都插入了同一类型的数据,使用时我们也需要将它们转化为对应的原类型来处理

    ArrayList 存储在装箱和拆箱操作,导致其性能低下

           //装箱
            int i = 123;
            object o = i;
 
            //拆箱
            object o1 = 123;
            int i1 = (int)o1; //强制类型装换

List  泛型集合

   List 与其他数组的比较ÿ

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值