C#知识点

  1. 语句:

语句是构造所有C#程序的构造块,通常以分号结束语句。一个大括号括起来一系列语句构成的代码块。语句可以声明局部变量或常数,调用方法,创建对象或将值赋予变量、属性或字段。

语句包含:选择语句,循环语句,跳转语句,异常处理语句

A:条件语句包括:if……else ,switch….case..default

1) if(bool类型的判断语句)

{

当bool值为true时执行的代码

}

else

{

当bool值为false时执行的代码

}

2) switch….case..default的基本用法为:

switch(需要判断的变量)

case 变量的值:

{

当变量的值与该变量相同时执行的代码

}

break;

defult:

break;

B :循环语句:while语句,do..while语句,for语句,foreach语句

1)While的用法:

while(返回值为bool型的变量)

{

当bool值为true时执行该段代码,否则跳出循环

}

2)do….while的用法:

do

{

无论while后的bool值是否为空该段代码都会被执行,若bool值为false会在执行一次后跳出循环

}while(返回值为bool型的变量)

3)for循环的用法:

for(可赋值的变量=初始值;变量的范围;变量依次变化量)

{

满足条件执行的代码

}

 

 

示例:

for (DateTime dt = DateTime.Parse("2010 - 7- 1"); dt < DateTime.Now; dt=dt.AddDays(1))

{

Console.WriteLine(dt.ToString());

}

4)foreach语句的用法

foreach(变量类型  变量名  in  集合或数组)

{

Code

}

C,跳转语句主要有:goto,continue,break,throw

1,goto语句:跳转到特定的位置例如:

goto Mark;

       Console.WriteLine("第一行");

     Mark:

       Console.WriteLine("第二行");

在以上代码中程序遇到goto就转到Mark处因此不会执行Console.WriteLine("第一行");而直接执行Console.WriteLine("第二行");

2,break:跳出循环

3,continue:跳出本次循环

4,throw:抛出异常

 

  1. 结构

结构是一种值类型继承自ValueType,通常用于封装小型相关变量组,结构与类不同无法用new运算符实例化,结构中有默认的参数为0的构造函数,与类不同的是,当你为结构自定义一个构造函数时它的默认构造函数不会消失,因此定义结构的构造函数时必须带有参数。结构可为null值,结构可以实现接口。结构的声明需要关键字struct,结构的修饰符可以是public,internal默认修饰访问符为interal

 

  1. 枚举

用来声明枚举的关键字为:enum 枚举类型也是值类型。

例如:

enum Menu

 {                              

            文件 = 1,         

            编辑 = 2,

            视图 = 4,         

 }

1,2,4为枚举数的值,默认情况下为0,1,2枚举的值可以为除了char类型以外的任何整型,后面每个枚举数的值一次递增1。当第二个枚举名为0.第一个默认时,第一个枚举的值也为0,枚举中枚举的值可以重复。

枚举类型的属性枚举又称为位标志例如:

[Flags]

        enum Menu

        {

            文件=1,

            编辑=2,

            视图=4       

        }

 

 Menu m = Menu.编辑|Menu .文件;

 Console.WriteLine(m);

把枚举数的值定义为1,2,4等2的倍数可以输出多个枚举值。按枚举的值在程序中自动输出枚举的名称

  enum Sex//定义性别

    {

        男,

        女,

    }

    class Program

    {

        static void Main(string[] args)

        {

            foreach (string s in Enum.GetNames(typeof(Sex)))

            {

                Console.WriteLine((int)Enum.Parse(typeof(Sex),s)+s+",");

            }

 

        }    

}

  1. 值类型和引用类型

值类型派生自System. ValueType每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。值类型包括:简单类型,枚举类型,结构类型。

引用类型:引用类型的变量又称为对象,可存储对实际数据的引用。

给变量赋值时值类型仅仅把值传给变量,而引用类型则把地址传给变量,String是特殊的引用类型

  1. 装箱和拆箱

装箱是把值类型转化成引用类型,拆箱即是取消装箱,是把引用类型转化成值类型,装箱时没有要求,在拆箱时必须知道装箱前变量的类型,拆箱后的变量类型必须与装箱前相同。

  1. String和StringBuilder

string是一个特殊的引用类型,是任何程序使用最多的类型之一,string是直接赋值来构造的,不能用new来实例化,string一旦定义是不可变的,如果字符串发生变化就会生成新的字符串。当定义一个字符串时在托管堆中给字符串分配一个空间,当字符串变化时托管堆中为新的值分配空间,旧的空间与字符串的链接会自动断开,通过垃圾回收,收回该字符串在托管堆中的空间,例如:string a="abcs";string b=a;sting a="ebe"当b=a时把托管堆中的a的地址也指向b当a发生变化时托管堆中为a开辟一个新的空间,把a与新空间链接起来,但b的链仍然不变,当b再放生变化时“abcs”在托管堆中的空间会被垃圾回收。

string中主要的函数为:

compare:比较两个指定的string对象返回值为:int类型当两个string变量相同时返回0,否则返回-1;

concat:把其他形式转换成字符串形式 例如: int[]a={1,2,3};   string b= string.Concat(a[1]);他把数组a转变成字符串形式的数组

例如  string a = "dddd";string b = "wwww";string c = string.Concat(a, b);Console.WriteLine(c);输出结果为dddwwww,即把两个字符串转变成一个字符串

StringBuiler:String是不可变的,如果发生拼接就会造成性能上的浪费。当拼接时string会在托管堆中重新开辟一个空间存放拼接后的字符,这样造成了性能上的浪费,StringBuiler可以有效的对字符串进行动态的操作,通过维护char数组来达到操作字符串

在下面两种情况下会分配新对象:

  1. 试图动态构造一个字符串,它的长度超过了事先设置的容量。
  2. 试图在调用了StringBuilder的ToString方法之后修改数组。
  1.  数组

Array提供了创建、操作、搜索、排序数组的方法,所有Array是所有用作数组的基类。Array数组不能new只能通过CreateInstance方法来创建例如:

Array MyArr = Array.CreateInstance(typeof(int), 5);

MyArr.SetValue(1, 0);

MyArr.SetValue(2, 1);

一维数组的定义四种方式:1,int[]ar=new int[2]{1,2}  2,int[]arr=new int[]{1,2}; 

3,int []arr=new int[2];arr[0]=1;  4,int []arr={0,2};

二维数组的定义:int[,]arr={{0,2},{4,54}};   arr[1][0]

交错数组:

int[][] arr = new int[2][] { new int[] { 1, 2, 3 }, new int[] { 4 } };

也可以定义为:int[][] arr = new int[2][] { { 1, 2, 3 },{ 4 } };

遍历数组时二维数组用arr.GetLength(0)表示,交错数组用arr[i].Length表示,数组都为引用类型。

 

  1. 集合

集合是一组组合在一起的类似的类型化对象。集合有ArrayList,Quere,Stack,Hashtable,List<T>

ArrayList:用法为:ArrayList al = new ArrayList();al.Add(1);当添加的是值类型时会发生装箱,拆箱操作需要使用较多的空间资源

Stack是表示对象先进后出的集合

Queue是表示对象先进先出的集合

Hashtable:表示键/值对的集合,这些键/值对根据键的哈希代码进行组织。

List<T> :是 ArrayList 类的泛型等效类。该类使用大小可按需动态增加的数组实现 IList<T> 泛型接口。T是一个类型参数,标明列表中元素的准确类型,而不是ArrayList中的object中的类型。类型可以是值类型也可以是引用类型。因此不需发生装箱和拆箱操作

类是一组具有相同数据结构和相同操作的对象的集合。类是对一系列具有相同性质的对象的抽象,是对对象共同特征的描述。

类中的成员有:

 sealed

  1. c#中的访问修饰符:

public,protected,internal,private

由他们组成的访问级别有:

1)public:访问不受限制。

2)protected:访问仅限包含类或从包含类派生的类型

3)internal:访问仅限于当前程序集。

4)private:访问仅限于包含类型。

5)protected+internal:访问仅限于当前程序集或从包含类派生的类型。

除了protected+internal,成员或类型只能有一个访问符,结构和类的默认访问权限为internal方法的默认访问权限为:private。enum默认的成员中的可访问性为public,class中成员的可访问性为private,interface中的成员为public,struct中成员为private,命名空间不允许有访问修饰符。

2、构造函数:

每个结构和类都有默认的构造函数,类中加入自定义的构造函数后,默认的会自动消失,结构中默认的构造函数不会消失,因此结构中的构造函数必须加参数。构造函数初始化所有字段,它的方法名与类名相同且无返回值类型,实例化类时new的作用:1。分配内存 2。实例化类中的字段和方法

类中出现静态构造函数的方法为:1。自定义一个静态构造函数,2。定义一个静态的字段

有多个构造函数时先调用静态构造函数,静态构造函数不能有参数和访问修饰符。

3。析构函数

析构函数无访问修饰符,如:~MyClass()析构函数一般不使用,当一段代码占用大量资源时才会用析构函数释放资源。不能在结构中定义析构函数。只能对类使用析构函数。一个类只能有一个析构函数。无法继承或重载析构函数。无法调用析构函数。它们是被自动调用的。析构函数既没有修饰符,也没有参数。

4。索引器

索引器允许类或结构的实例就像数组一样进行索引。索引器类似于属性,不同之处在于它们的访问器采用参数。使用索引器:

1。使用索引器可以用类似于数组的方式为对象建立索引。

2。get 访问器返回值。set 访问器分配值。

3。this 关键字用于定义索引器。

4 。value 关键字用于定义由 set 索引器分配的值。

5。 索引器不必根据整数值进行索引,由您决定如何定义特定的查找机制。

6。 索引器可被重载。

7。 索引器可以有多个形参,例如当访问二维数组时。

 class DayCollection

    {

     string[] days = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };

     private int GetDay(string testDay)

        {

            int i = 0;

            foreach (string day in days)

            {

                if (day == testDay)

                {

                    return i;

                }

                i++;

            }

            return -1;

        }

      public int this[string day]

        {

            get

            {

               return (GetDay(day));

            }

        }

    }

【索引器,索引器允许以数]的形式访问元素,可以定义整形和非整形两种下标】

    class Program

    {

        static void Main(string[] args)

        {

            DayCollection week = new DayCollection();

            System.Console.WriteLine(week["Fri"]);

            System.Console.WriteLine(week["Made-up Day"]);

        }

    }

该程序输出结果为:5  -1

 

  1. 方法参数

方法的传递时参数:分引用类型,值类型,ref参数,out参数,params参数

1。当参数为值类型时这时方法中改变参数的值是没有用的例如:

 public void method1(int i)

      {

          Console.Write(i);

          i = 100;

 

      }

  static void Main(string[] args)

        {

            Myclass mc = new Myclass();

            int i = 7;

            mc.method1(i);

            Console.WriteLine(i);

        }

打印出的结果为:7,7。具体实现为:int类型为值类型,当调用mc.method1(i)时i把值传给方法method1,也就是调用方法时把7传给method1的i,即输出7,当方法中i=100时,也就是令7=100;在main方法中i的值是不发生变化的。

2。当参数是值类型时在参数前加ref会把值参数的地址传给方法,这与引用类型基本是一样的例如:

  public void Method3(ref string i)

        {

            Console.WriteLine(i);

            i = "100";

        }

  static void Main(string[] args)

        {

             Myclass mc = new Myclass();

            int i = 7;

            mc.Method3(ref  i);

            Console.WriteLine(i);

        }

输出结果为7,3 具体实现为:ref把i的地址传给方法Method3当空间中i发生变化时地址空间也变化,所以方法结束后i的值也变化。

 

 3。out 作参数能够返回多个值。例如:

 public void Method4(out int i, out string j)

        {

            i = 100;

            j = "10";

            Console.WriteLine(i+j);

        }

  static void Main(string[] args)

        {

          MyClass mc = new MyClass();

           int i = 10;

            string j;

            mc.Method4(out i, out j);

            Console.WriteLine(i);

           Console.WriteLine(j);

         }

 

结构为:100 10,100,10在调用时变量不需要赋值,在方法中会把赋的值修改

4。方法中使用动态参数例如:

 public void Mehtod5(string t, params int[] arrint)

        {

            foreach (int i in arrint)

            {

                Console.WriteLine(i);

            }

       

        }

   static void Main(string[] args)

        {

 

            Program mc = new Program();

            int[] arrint = new int[] { 1, 2, 3 };

            mc.Mehtod5("dd", arrint);

          

        }

输出结果为:1 2 3 params使参数为数组,数组的长度是可变的

 

5。当方法中的参数为引用类型时,传递的是地址,例如:

 

  public void method1(int[]arrint)

      {

          foreach (int a in arrint)

          {

              Console.WriteLine(a);

          }

          arrint[0] = 1222;

 

      }

    static void Main(string[] args)

        {

            int[] arrint = { 1,2,3,4};

          

            Myclass mc = new Myclass();

            mc.method1(arrint);

            foreach (int a in arrint)

            {

                Console.WriteLine(a);

            }

        

        }

输出结果为:1,2,3,4  1222,2,3,4 地址传给方法后在方法中参数变化即地址也发生变化,再调用时就发生变化。

  1. 分部方法,扩展方法,匿名方法

分部方法是在分部类中定义的分部方法,关键字为:partial,分部方法是在一个分部类中声明方法签名,在另一个分部类中定义方法体,分部方法也可在一个类中定义,但是少了分部方法的作用。分部方法的返回值必须为void,可以有ref但不能有out参数,分部方法为隐式private因此不能为virtual,分部方法不能扩展,分部方法可以有static和unsafe修饰符,分部方法可以为泛型,不能将委托转换为分部方法。不能为静态类定义扩展方法

扩展方法:扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。扩展方法是在静态类中定义的静态方法。

扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。它们的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀。仅当您使用 using 指令将命名空间显式导入到源代码中之后,扩展方法才位于范围中。例如:

public static int WordCount(this string str)

        {

            return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;

        }

该方法是为string的扩展方法

匿名方法:匿名方法不必定义方法名,通过使用匿名方法,由于您不必创建单独的方法,因此减少了实例化委托所需的编码系统开销。匿名方法的参数的范围是“匿名方法块”。

例如:

button1.Click+=delegate(System.Object o,System.EventArgs e) { System.Windows.Forms.MessageBox.Show("Click!"); };

  1. 字段,属性

字段是类或结构中的对象或值类和结构使用字段可以封装数据。字段通常应为 private。外部类应该通过方法、属性或索引器间接访问字段。字段的初始化紧靠调用对象实例的构造函数之前。如果构造函数为字段赋值,则该值将覆盖字段声明期间给出的任何值。可以将字段声明readonly。只读字段只能在初始化期间或在构造函数中赋值。static readonly 字段非常类似于常数,只不过 C# 编译器不能在编译时访问静态只读字段的值,而只能在运行时访问。

属性:它们提供灵活的机制来读取、编写或计算私有字段的值。可以像使用公共数据成员一样使用属性,但实际上它们是称作“访问器”的特殊方法。这使得可以轻松访问数据,属性通过get和set访问器来操作数据。

  1. 委托

委托是一种引用方法的类型,一旦为委托分配了方法委托将与改该方法具有完全相同的行为。

委托的特点:

1。委托类似于 C++ 函数指针,但它们是类型安全的。

2。委托允许将方法作为参数进行传递。

3。委托可用于定义回调方法。

4。委托可以链接在一起;例如,可以对一个事件调用多个方法。

5。方法不必与委托签名完全匹配。

委托的使用:

1。委托的定义:delegate void Dele(int i);

 2。定义方法:

public void Method(int i)

        {

            Console.WriteLine("参数为:{0}",i);

        }

3。关联委托和方法:

Program pro = new Program();

Dele del = new Dele(pro.Method);

del(100);

下面是一个委托的例子:

public class MethodClass

{

    public void Method1(string message) { }

    public void Method2(string message) { }

}

MethodClass obj = new MethodClass();

Del d1 = obj.Method1;

Del d2 = obj.Method2;

Del d3 = DelegateMethod;

 

//Both types of assignment are valid.

Del allMethodsDelegate = d1 + d2;

allMethodsDelegate += d3;

 

  1. 事件

事件:类或对象可以通过事件向其他类或对象通知发生的相关事情。发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。事件本质上是一组方法。

事件的使用步骤:

 delegate void DL();①

   class TimeOpe

   {

       public event DL sj;②

       int step;

 

       public int Step

       {

         

           set { step = value; }

       }

       public void Begin()

       {

           while (step > 0)

           {

               Console.WriteLine("下课");

               Console.WriteLine(DateTime.Now.ToString());

               Thread.Sleep(2000);

               step--;

           }

           sj();⑤

       }

   }

   class myclass

   {

       static void Main()

       {

           TimeOpe to = new TimeOpe();

           to.sj += show;④

           to.Step = 1;

           to.Begin();

       }

      static  void show()③

       {

           Console.WriteLine("上课");

           Console.WriteLine(DateTime.Now.ToString());

       }

  

   }

输出结果为:

下课

2010-7-26 16:38:18

上课

2010-7-26 16:38:20

①定义一个与方法相应的委托

②定义关于方法和委托的事件

③定义事件方法

④订阅方法

⑤响应该事件

  1. 静态类,密封类,抽象类

1,)密封类

关键字为:sealed,放于class前,密封类不能用在基类,密封类的主要作用为:防止派生

2)静态类

静态类在加载包含该类的程序或命名空间时由 .NET Framework 公共语言运行库 (CLR) 自动加载。

静态类的主要功能:

1.它们仅包含静态成员。

2.它们不能被实例化。

3.它们是密封的。

4.它们不能包含实例构造函数。

静态类中的构造函数不能有访问修饰符和参数,静态类不能被继承也不能继承其他自定义的类。静态方法可以被重载但不能被重写

3)抽象类

关键字为:abstract。抽象类不能被实例化。抽象类中的实例化函数不可以被调用,只有通过子类来调用。静态函数可通过类名.方法名来调用。抽象类中不能有抽象构造函数也不能有抽象字段。抽象类的访问修饰符不能为private

  1. 接口

接口的关键字为:interface,接口中只能有public访问修饰符而且public不能手动再次输出。接口也不能被实例化。

  1. 虚方法,重载方法

虚方法:有关键字virtual的方法为虚方法,虚方法可以在子类中重写,重写的关键字为override,在子类中也可不重写,子类中的重写覆盖父类的虚方法。

重载方法:是方法名相同,方法的参数类型或数量不同。

  1. 继承

继承的方法在子类后加冒号,冒号后加父类名例如:

public class A

{

 public a()

 {

   Console.WriteLine("A的构造函数");

 }

}

public class B : A

{

public b()

  {

  Console.WriteLine("B的构造函数");

  }

}

static void Main()

{

B b=new B();

}

新类(即派生类)将获取基类的所有非私有数据和行为以及新类为自己定义的所有其他数据或行为。

构造函数的调用:以上代码为例:当实例化B时,先调用A的构造函数,再调用B的构造函数,B的构造函数默认继承base()若代码为下例:

public class A

{

 public A(int i)

 {

   Console.WriteLine("A的构造函数"+i);

 }

}

public class B : A

{

public B()

  {

  Console.WriteLine("B的构造函数");

  }

}

这个例子是不正确的,当实现B的构造函数时会向上查找与B类构造函数匹配的A的构造函数B构造函数默认继承base(),但A中不存在构造函数

public A()

 {

   Console.WriteLine("A的构造函数");

 }

base()表示父类对象,this表示本类对象。

继承的子类中可以有和父类方法签名相同的方法当调用时父类方法被隐藏,若在子类方法名前加new时称为显示隐藏否则为隐式隐藏。

不允许循环继承,继承时调用只会影响子类。

方法的重写:在父类的方法前加virtual说明方法定义为虚方法,可以在子类中重写该方法,重写的是前一个virtual的方法。

 

  1. 面向对象的思想

 

封装:用抽象的数据类型将数据和基于数据的操作封装在一起,数据被保护在抽象数据类型内部。

继承:子类拥有父类的所有数据和操作。

多态:一个程序中同名的不同方法共存的情况。有两种形式的多态– 重载与重写。  总精简的描述:通过继承实现的不同的对象,实现相同的方法,表现出不同的行为,称之为多态

 

  1. readonly和cosnt的异同

ü  异:(1)readonly修饰实例字段,const修饰类字段;(2)readonly可以在声明和构造函数两处赋值,const只能在声明时赋值。

ü  同:一经赋值,不可改变

 

  1. 异常

C# 语言的异常处理功能提供了处理程序运行时出现的任何意外或异常情况的方法。异常处理使用 try、catch 和 finally 关键字来尝试可能未成功的操作,处理失败,以及在事后清理资源。异常可以由公共语言运行库 (CLR)、第三方库或使用 throw 关键字的应用程序代码生成。

异常处理语句:异常处理有try,catch,finally构成,try语句是必须存在的,catch和finall可全出现也可省略一个但是必须出现一个

try

{

可能会出现异常

}

Catch

{

捕捉异常

}

Finally

{

代码执行完后释放资源

}

  1. 泛型

泛型是C#2.0和CLR(公共语言运行时)升级的一个新特性,泛型为.NET 框架引入了一个叫 type parameters(类型参数)的概念,type parameters 使得程序在设计的时候,不必设计其具体的参数,其具体的参数可以延迟到需要的时候声明或调用。使用泛型代码运行时避免了类型转换的装箱和拆箱操作。

  • 2.0 泛型的延迟声明:把参数类型的声明推迟到调用,不是语法糖,而是由框架升级提供的功能
  • 3.0 泛型主要的四种:泛型类, 泛型方法,泛型接口,泛型委托  

/// <summary>

/// 泛型类

/// </summary>

/// <typeparam name="T">类型参数</typeparam>

/// <typeparam name="S">类型参数</typeparam>

/// <typeparam name="K">类型参数</typeparam>

public class GenericClass<T, S, K>

{

    /// <summary>

    /// 无返回值的泛型方法

    /// </summary>

    /// <typeparam name="T"></typeparam>

    public void Show(T t)

    {

 

    }

    /// <summary>

    /// 有返回值的泛型方法

    /// </summary>

    /// <typeparam name="T"></typeparam>

    /// <returns></returns>

    public T Get()

    {

        return default(T);

    }

}

 

/// <summary>

/// 泛型接口

/// </summary>

/// <typeparam name="W"></typeparam>

public interface ISleep<W>

{

    W Sleep(W t);

}

 

/// <summary>

/// 有返回值的泛型委托

/// </summary>

/// <typeparam name="Y"></typeparam>

/// <returns></returns>

public delegate Y DlgYFun<Y>();

  • 4.0泛型的约束(基类约束,接口约束,引用类型约束,值类型约束,无参构造函数约束)

/// <summary>

/// 泛型约束

/// </summary>

public class Constraint

{

 

    public static void Show<T>(T tParameter)

        //where T: AnimalModel  基类约束,就可以访问该类的方法或属性

        where T : Cat //或者该子类      

    {

        Console.WriteLine("泛型约束show方法--------id={0},name={1}", tParameter.Id, tParameter.Name);

    }

 

    public static void Show(AnimalModel model)

    {

        Console.WriteLine("普通show方法--------id={0},name={1}", model.Id, model.Name);

    }

 

    public static void ShowInterface<T>(T tParameter)

        //where T: AnimalModel  基类约束,就可以访问该类的方法或属性

        where T : Cat, ISleep, IEat//或者该子类约束,多个接口约束

    {

        Console.WriteLine("泛型约束ShowInterface方法--------id={0},name={1}", tParameter.Id, tParameter.Name);

        tParameter.Sleep();//接口的方法

        tParameter.Eat();

    }

}

说明:Constraint类里的第一个show方法中在后面带个 where关键字 和 约束类型,泛型方法里就能访问Id和Name,第二个show方法是作为对比,虽然第二个方法也能实现同样的效果,但是相对泛型方法不灵活,泛型方法可以同时约束多个,比如第三个方法约束多个接口,和类,多个约束的关系是&&关系

泛型约束除了基类约束和接口约束几种,还有值类型约束,无参构造约束,引用类型约束等这几种。
基类约束:
1带来权利,可以使用基类里面的属性和方法。
2带来义务,类型参数必须是基类或者其子类。

  • 5.0协变和逆变

 out 协变(covariant) 修饰返回值,in 逆变(contravariant) 修饰传入参数。out和in只能放在接口或者泛型委托的的参数前面,类没有协变和逆变。在.NET Framework里面,IEnumerable<T>转到定义去看,其实就是个带out参数的泛型接口,Action<T>转到定义去看就是个带in参数的泛型委托。还有一个逆变+协变的Func<T>。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值