【笔记-C#】C#

  1. 命名空间

可以通过using重定义类型名

using NewMsgSizeType=UInt32;

可以在命名空间A内嵌套命名空间B,相当于在A内定义一个变量B,所以A和B不能互相访问元素。

命名空间内只能包含类,枚举,结构体,委托等,不能包含变量和函数。

默认情况下存在一个全局命名空间,所以在命名空间外定义的类可以直接进入到此全局命名空间。在全局命名空间中包含的类内写static变量,就相当于全局变量。

  1. 基本数据类型
    1. 基本类型

类型

字节数

描述

Byte

1

unsigned byte

Sbyte

1

signed byte

Short

2

signed short

Ushort

2

unsigned short

Int

4

signed integer

Uint

4

unsigned integer

Long

8

signed long

Ulong

8

unsigned long

Float

4

floating point number

Double

8

double precision number

Decimal

8

fixed precision number

String

Unicode string

Char

2

Unicode char

Bool

true,false,boolean

    1. 可空类型

int? x = 5; //x可以赋值为null

与非可空类型运算时,需要显示转换

int y = (int)x* 2;或者int y = x.Value * 2;

??运算

允许给值可能为null的表达式赋另外一个值

x??y  等价x==null?y:x

使用时如:

int? x = null;

int result = x * 2 ?? 5;

结果为5

    1. Var

可以指代任何类型的变量

var x="***";

var a = new A();

class类型必须用new,在函数中传递时是引用传递(可以不用ref,但在函数中不能改变class对象的指向)。

    1. 静态成员

因为C#没有全局变量和函数。Static成员不属于对象实例,所以可以在不实例化类的情况下直接调用。

C#中,const变量也可以被static函数调用。

静态变量可以用来在类与类之间进行数据交互和共享。

class A{ public static int x=10;}

在其他任何地方,都可以使用A.x进行访问。

    1. 属性

属性比字段(变量)包含的内容多,在修改状态时还可以进行额外的操作。

包含两个函数块(get和set),一个用于获取属性,一个用于设置属性。这两个块也称为访问器。

class Data

{

        int month=10;//私有的,外部不能直接访问

        public int Month //指代变量

        {

            get { return month;}

            set { month = value;}

        }      

}

使用时

Data data = new Data();

data.Month = 20;//设置

int x=data.Month;//获取

自动属性

public int x { set; get; }

    class Cu

    {

        public string Name { get; set; }

        public string City { get; set; }

}

Cu c = new Cu() { Name = "ab", City = "12" };

    1. 权限

只能修饰单个成员,不能用public:修饰下面的所有成员。

类可以用internal修饰,表示只能在当前项目访问。子类的可访问性不能高于父类(internal可以继承public,反之不可)。

可以用public,private,protected修饰

readonly  

只能在初始化或者执行构造时赋值。仅用于修饰类的数据成员,和const不同之处在于const要求在声明时进行直接初始化,readonly是指一旦进行了写操作或者初始化,就不可以修改。

readonly修饰变量不能在函数中定义,只能修饰类的成员变量。

sealed

可以用来修饰类,该类不允许被继承。

    1. 构造

class A

{

     int x, y;

     public A(int x,int y)

     { this.x = x; this.y = y;}

}

使用时:A a = new A(1, 3); //带参数的构造函数只能用new调用

A a;  //该方式和无参构造无关,在类内定义无参构造没有意义,即使定义为private也可以。

    1. 多态

父类使用virtual关键字,子类实现虚函数使用override关键字。

class B

{

    public virtual void fun() {Console.WriteLine("B");}

        

}

class C : B

{        

    public override void fun(){Console.WriteLine("C");}

}

使用时:

B b=new C();

b.fun(); //输出C

和C++概念相同,父类指向子类,本质还是父类(忽略子类中除了父类以外的内容),子类只是用来改写父类的虚函数。

如果父类和子类有重名的函数或者变量,使用base在子类中引用父类的成员:base.fun();

    1. 继承

如果没有指定继承的父类,那么就是默认只继承自System.Object。所以,每个类都是继承自System.Object。

子类中有和父类相同的成员,就会隐藏父类的成员。使用base关键字就可以访问被隐藏或者重写的父类成员,如base.fun()。

class A{A(int x){} }

class B : A {//没有protected和private继承 

B():base(5){} //初始化参数列表中用base关键字指定父类构造中需要的参数

}   

    1. Abstract

主要用作对象系列的基类,共享某些主要特性。

抽象类不能直接实例化,也可以和接口一样声明函数,由派生类实现。

abstract class A

{

    int x;

    public void fun1(){Console.WriteLine("aa");}

    public abstract void fun2();

}

class B : A

{

    override public void fun2(){Console.WriteLine("xx");}

}

    1. 释放对象

using(x){.......}

在using的代码块中使用变量x,代码块结束后,立即释放对象。

    1. partial

使用partial关键字可以让一个类在不同的文件中定义

============文件1内

namespace N

{

     partial class A

    {

         public void fun1() { Console.WriteLine("fun1"); }

         partial void fun3();//这种只声明,不实现的函数必须是void,而且不能用public这种修饰。如果声明的这个函数没有被实现,编译器就会在编译时自动删除相关代码。

    }

}

============文件2内

namespace N

{

    partial class A

    {

        public void fun2() { Console.WriteLine("fun2"); fun3(); }

        partial void fun3() { Console.WriteLine("fun3"); }

    }

}

============使用时

using N;

A a = new A();

a.fun1();

a.fun2();

  1. Object

可以指代任何对象

       void fun(object[] obj)

        {

            foreach(object o in obj)

                Console.WriteLine(o);

        }

  fun(new object[]{1,3.3,"adf"});

  1. 接口

interface X1{ void fun1();  void fun2();}//声明接口

interface X2 { int a { get; } }

class X : X1, X2 //用多继承接口,并实现接口

{

   void X1.fun1() {Console.WriteLine("fun1");}//显示实现

   public void fun2(){Console.WriteLine("fun2");}//隐式实现

public int a { get;protected set; } //实现时必须要get,set同时存在,如果接口中不存在其中一个,就要添加。添加时修饰符必须要比接口中的严格(接口是public,所以此处可以用protected)

}

调用时

X x = new X();

X1 x1 = (X1)x; //将类转换为某一接口的内容

x1.fun1();

x.fun2();

  1. 委托

可以把函数引用保存在变量中,类似于函数指针。使用关键字delegate。

delegate void fun(int x);

void fun1(int x){}

void fun2(int x){}

//创建对象调用

fun ff = new fun(fun1);

ff(1);

//直接调用

fun ff = fun1;

ff(1);

//Lambda

fun ff = (int x) => { Console.WriteLine("{0}", x); };

ff(1);

//事件

fun ff = fun2;

ff += fun1;

ff += fun3;

ff -= fun1;

ff(1); 

  1. Attribute

using System.Diagnostics;

添加额外信息

    1. 内置attribute

函数只在debuge下有效

[Conditional("DEBUG")]

void fun(){}

[Obsolete("过时的方法",true)]    第二个参数为编译时是否报错

 void fun(){}

    1. 自定义attribute

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]

        //代表该Attribute只能用在class上一行,不能连续两行出现该Attribute,类在继承时不继承该Attribute

        class MyAttrbute : Attribute

        {

            public string info;

            public MyAttrbute(string msg)

            {

                info = msg;

            }

            public int vale = 0;

        }

使用时:

 [MyAttrbute("xxxxx", vale = 11)]

  class Test{}

通过反射获取信息:

          foreach (var attr in typeof(Test).GetCustomAttributes(true))

            {//获取Test类的所有Attribute,找到MyAttrbute进行处理

                MyAttrbute myAt = attr as MyAttrbute;

                if (null != myAt)

                {

                    Console.WriteLine(myAt.vale);

                }

            }

  1. 函数
    1. 引用传递

void fun(ref int x){....}

调用时(ref也是函数签名的一部分,所以调用时候也要写上。传入的参数必须有初始化[赋值]),class类型如果只是在函数中改变值,不改变指向,可以直接传递,不用ref。

int x=10;

fun(ref x);

    1. 输出参数

类似于ref,不同处在于传入的变量可以没有初始化(赋值)。在函数中,要把传入的变量作为未初始化的来处理,也就是在函数中必须要进行初始化(赋值)。

void fun(out int x){x = 10;....}

      

int x;

fun(out x);

    1. 不定长参数

可以声明为不确定参数个数(数组类型),该参数必须总是函数最右边的参数,且只有一个参数可以是数组类型。

下面的函数调用时可以使用:int max=fun(1,3,243,434,12);

int fun(params int[] a)

  1. 数据类型
    1. 用户类型

包括类,结构体,枚举(和C++完全一样),接口。

除了内存分配,类和结构与C++完全相同。

类的对象在堆中分配,使用new创建(构造函数必须加上()),当不再使用时,将自动进行垃圾清理。

结构是在栈中分配。属于轻量级快速数据类型。

    1. 结构体

结构体是值类型,而类是引用类型。

结构体没有构造函数,也不能在定义变量时赋值。

struct data

{

     public int a ;

     public float b;

 }

data d;

d.a=10;

d.b=1.1f;

    1. 枚举

enum E{a,b,c}

E e=E.a;

if (e == E.a){.......}

enum E:uint{a=1,b=2}

int x=(int)E.a;

  1. 字符串

 string s1 = "scca";//”scca”字面值本身就是string类型

 string s2 = new string('c', 5);

 char[] a = { 'a', 'b', 'c','\0'};//可以不加\0

 string s3 = new string(a);

========@转译

适合地址的转换

@”d:\1.avi

或者string  addr=”d:\1.avi”;  string str=@addr;

========转换为其他类型

int x = Convert.ToInt32("12");

========其他类型转换为字符串

int  x=10;

string s=x.ToString();

========转换为字符串数组

char[] a = s.ToCharArray();

========去除开头和结尾多余的空格:

s=s.Trim();

========加入字符

string s = "abc";

s=s.PadLeft(5');//可以在s前面加入两个空格,因为s原长3,要补足到5,所以加入2个

s=s.PadLeft(5,'_');//加入两个_

========分割字符串

str = str.Substring(pos,length); //从pos截取length长度(无length代表到结尾)

string s = "abc|de|fg ";

string[] str = s.Split('|');//用str.Length可以求出数组长度

foreach (string i in str)

{

    Console.WriteLine(i);

}

========字符串查找

bool b=str.Contains("xxx");

  1. 字符串格式化

string s = string.Format("{0:D3},{1:n2}", 10, 1.23234);   

//:D3表示整数至少3位,不足高位补0

//:n2表示小数点后保留2位

:c   货币形式

:x  十六进制

:000.00    用0填充不足的位数,小数点后固定两位

  1. 数组

数组分配于堆中,是引用类型。

    1. 定义

int[]  a=new int[10];

int[] a =new int[5]{ 34, 12, 32, 43, 32}

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

二维数组

int[,] a = new int[5, 10];//或者int[,] a={ { 3, 4 }, { 3, 2 } };

a[1,2]=5;// 赋值

    1. 遍历

数组可以用foreach循环

foreach (int x in array){...}

    1. 拷贝

将数组a的内容拷贝到数组b,数组b接收拷贝的位置是从b[2]开始

a.CopyTo(b, 2);

    1. 功能函数

int len = a.GetLength(0);//得到数组中元素个数,0代表这是一维数组

     或者使用int len=a.Length;

int index = a.GetUpperBound(0);//得到数组最大下标数

    1. Linq

int[] numbers = {3,5,2,5,12,5,36,75,42};

var qur = numbers.Where((n) => n % 2 == 0).OrderBy((n) => n);

foreach (var i in qur) Console.WriteLine(i + "");

int[] ret = qur.ToArray<int>();  

  1. 预处理
    1. region

当代码比较长,可以定义分组,这样就可以折叠这个区域

#region A

.................

#endregion

    1. define

#define De             //在文件最开头定义一个标志    

#undef De  可以进行取消定义

    1. 条件判断

如果有定义则代表会进行编译,否则会隐藏

#if De

            Console.WriteLine("de");

#endif

    1. 编译消息

在文件中定义后,编译文件会弹出警告或者错误

#warning xxx

#error xxx

可以修改在编译时弹出的行号,字符串可以修改当前提示的文件名

#line 100  "flileName"

    1. Pragma

#pragma warning disable 123

#pragma warning restore 123

  1. 修饰符
    1. unsafe 

修饰在C#中定义的不安全的上下文,如C++的指针等。如:

public unsafe fun(int *p){  }

    1. checked

checked(….)可以检查表达式是否有溢出,如果有溢出,则程序会崩溃。

    1. lock

类似于互斥锁。

将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁,lock确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,将一直等待,直到该对象被释放。

object locker = new object();

lock(locker){ ......... }

    1. case

可以用常数变量作为判断值。必须有break跳转,不支持执行完一个case执行别的case。

可以使用以下方法执行多个case

case 2:

case 3:  Console.WriteLine("3");    break;

  1. 转换类型
    1. is

用于检查操作数类型是否相等或可以转换,使用两个操作数,其结果是布尔值。适合于多态的情形。

if(a is ClassA){......................}

    1. as

检查操作数的类型是否可以转换或者相等(是由is完成的),如果是,则处理结果是已转换或已装箱的对象。如果否,则返回null。

ClassA  a=new ClassA();

ClassB  b=a as ClassB; //返回值null,不可转换

ClassC  c=a;

ClassA  a2=c as ClassA; //将进行转换

    1. 重载转换

============定义

class A

{

     public int val=1;

     public static implicit operator B(A a)  //隐式转换

     {

          B b = new B();

          b.val = a.val;

          return b;

     }

}

class B

{

    public long val=1000;

    public static explicit operator A(B b)//显示转换

    {

         A a = new A();

         checked { a.val = (int)b.val; }

         return a;

     }

}

============使用

A a = new A();

B b = a;

            

B b = new B();

A a = (A)b;

  1. 装箱/拆箱

所有的数据类型都是从System命名空间的基类Object继承,所以基础或是原始的类型打包为一个对象,称为装箱。相反的处理称为拆箱。

int a1 = 10;      object obj = a1; //装箱

int a2 = (int)obj;//拆箱 

一个int值可以被转换为对象,并且能再次转换成int。

当某种值类型的变量需要被转换为一个引用类型时,便会产生一个对象箱保存该值,拆箱则完全相反。当某个对象箱被转换会其原值类型时,该值从箱中拷贝至适当的存储空间。

因为是装箱到obj,所以可以做一个List<object>,在读取的时候,通过使用is判断类型再拆箱(或使用as),实现不同类型放在同一个list中。

  1. 运算符重载

class A

{

     public int x =10;

     public static A operator+(A a1, A a2)

     {

          A a = new A();

          a.x = a1.x + a2.x;

          return a;

      }

}

可以重载的运算符

一元:+,-,!,~,++,true,false

二元:+,-,*,/,%,&,|,^,<<,>>

比较:==,!=,<,>,<=,>=

重载bool运算符就可以用  if(a1){}

  1. 初始化器

class A

{

    public string x { get; set; }

    public int y { get; set; }

}

A a = new A { x="a", y=1 };//这种方法可以不使用其他构造函数或者对象来初始化成员

List<A> l=new List<A>{new A{x="a",y=1},new A{x="b",y=2}};//可以替代l.add以及赋值的语法

  1. 异常

   public void fun()

   {

          throw new Exception("fun");

   }

                try

                {

                    fun();

                }

                catch (Exception e)

                {

                    Console.WriteLine(e.Message);

                }

                finally

                {

                    Console.WriteLine("try执行结束");

                }

  1. 索引器

使类可以通过[]语法访问和赋值。

class Test

{

        string Content1 = "aaa";

        string Content2 = "bbb";

        public  string this[int index]

        {

            get

            {

                if(index == 1) return Content1;

                if (index == 2) return Content2;

                return "erro";

            }

            set { }

        }

 }

Test test = new Test();

Console.WriteLine(test[1]);

  1. 类型获取

string s = "";

Type t1 = s.GetType();

Type t2 = Type.GetType("system.string", false, true);

 Type t3 = typeof(string);

  1. 反射
    1. 类信息

获取类中包含的可以访问的方法 

Type t = typeof(Cl);

MethodInfo[] mi = t.GetMethods();

foreach (MethodInfo info in mi)   

   Console.WriteLine(info.Name);

//获取单个方法

MethodInfo mi = t.GetMethod("fun1");

    1. 程序集

获取程序集中包含的类

 //Assembly obj = Assembly.Load("");

Assembly obj = Assembly.GetExecutingAssembly();

 Type[] types = obj.GetTypes();

         

 foreach (Type t in types)   Console.WriteLine(t.Name);

  1. 加载使用

加载当前程序集中的Cl类,void fun1(int i,string s)函数

  Assembly ass = Assembly.GetExecutingAssembly();

            Type t = ass.GetType("ConsoleApplication1.Cl", false, true);

            if (null == t) return;

           

            object obj = Activator.CreateInstance(t);//创建类的实例

            MethodInfo mi = t.GetMethod("fun1");

            mi.Invoke(obj,new object[]{1,"a"});

猜你喜欢

转载自blog.csdn.net/jiyanglin/article/details/81582901