C#语法基础总结

打印 上一主题 下一主题

主题 640|帖子 640|积分 1920

输入和输出

输入
Console.Read();
从屏幕读取一个字符,并返回该字符所对应的整型数字
Console.ReadLine();
从屏幕读取一串字符,并返回该字符串
输出
Console.WriteLine(); 输出内容,并换行
Console.Write(); 输出内容,不换行
using关键字

一般在程序开头添加 using System;,这时System.String 就可简写为string 。
using 关键字用于在程序中包含命名空间。一个程序可以包含多个 using 语句
  1. // using System;
  2. namespace ConsoleApp1
  3. {
  4.     class Program
  5.     {
  6.         static void Main(string[] args)
  7.         {
  8.             System.String a = "Hello World!";
  9.             System.Console.WriteLine(a);
  10.             System.Console.ReadKey();
  11.         }
  12.     }
  13. }
复制代码
  1. using System;
  2. namespace ConsoleApp1
  3. {
  4.     class Program
  5.     {
  6.         static void Main(string[] args)
  7.         {
  8.             string a = "Hello World!";
  9.             Console.WriteLine(a);
  10.             Console.ReadKey();
  11.         }
  12.     }
  13. }
复制代码
C#占位符{}



  • 当 WriteLine() 函数有多个参数时,输出第一个参数(双引号内的)中的内容,而第二个及反面的参数中的内容替换掉第一个参数中对应位置的占位符一起输出。
  1. static void Main(string[] args)
  2. {
  3.     Console.WriteLine("A:{0},a:{1}",65,97);
  4.     Console.ReadLine();
  5. }
复制代码


  • 如果第一个参数没有留占位符,那么第二个参数内容不输出 
  1. Console.WriteLine("A:,a:",65,97);
复制代码
C#数据类型

在C#中,变量分为以下几种类型:


  • 值类型(Value types)
  • 引用类型(Reference types)
  • 指针类型(Pointer types)
引用类型


引用类型不包含存储在变量中的现实数据,但它们包含对变量的引用。
  换句话说,它们指的是一个内存位置。利用多个变量时,引用类型可以指向一个内存位置。如果内存位置的数据是由一个变量改变的,其他变量会自动反映这种值的变革。内置的引用类型有:object、dynamic 和 string。
对象(Object)类型


   对象(Object)类型 是 C# 通用类型系统(Common Type System - CTS)中全部数据类型的终极基类。Object 是 System.Object 类的别名。所以对象(Object)类型可以被分配任何其他类型(值类型、引用类型、预定义类型或用户自定义类型)的值。但是,在分配值之前,需要先辈行类型转换。当一个值类型转换为对象类型时,则被称为 装箱;另一方面,当一个对象类型转换为值类型时,则被称为 拆箱。
  1. object obj;
  2. obj = 100; // 这是装箱
复制代码
动态(Dynamic)类型

您可以存储任何类型的值在动态数据类型变量中。这些变量的类型检查是在运行时发生的。
  1. dynamic <variable_name> = value;
复制代码
类型转换

类型转换从根本上说是类型铸造,或者说是把数据从一种类型转换为另一种类型。在 C# 中,类型铸造有两种情势:
隐式类型转换 - 这些转换是 C# 默认的以安全方式举行的转换, 不会导致数据丢失。比方,从小的整数类型转换为大的整数类型,从派生类转换为基类。
显式类型转换 - 显式类型转换,即强制类型转换。显式转换需要强制转换运算符,而且强制转换会造成数据丢失。
 下面的实例把差别值的类型转换为字符串类型:
  1. namespace TypeConversionApplication
  2. {
  3.     class StringConversion
  4.     {
  5.         static void Main(string[] args)
  6.         {
  7.             int i = 75;
  8.             float f = 53.005f;
  9.             double d = 2345.7652;
  10.             bool b = true;
  11.             Console.WriteLine(i.ToString());
  12.             Console.WriteLine(f.ToString());
  13.             Console.WriteLine(d.ToString());
  14.             Console.WriteLine(b.ToString());
  15.             Console.ReadKey();
  16.            
  17.         }
  18.     }
复制代码
动态常量(运行时常量) readonly

在运行时确定值,只能在声明时或构造函数中初始化,只能在类中定义。定义方法如下:
  1. class Program
  2. {
  3.     readonly int a=1;  // 声明时初始化
  4.     readonly int b;    // 构造函数中初始化
  5.     Program()
  6.     {
  7.         b=2;
  8.     }
  9.     static void Main()
  10.     {
  11.     }
  12. }
复制代码
?:运算符

我们已经在前面的章节中讲解了 条件运算符 ? :,可以用来替代 if...else 语句。它的一般情势如下:
  1. Exp1 ? Exp2 : Exp3;
复制代码
此中,Exp1、Exp2 和 Exp3 是表达式。请留意,冒号的利用和位置。
? 表达式的值是由 Exp1 决定的。如果 Exp1 为真,则盘算 Exp2 的值,结果即为整个 ? 表达式的值。如果 Exp1 为假,则盘算 Exp3 的值,结果即为整个 ? 表达式的值。
数组

1.一维数组初始化

动态初始化:
(1)数据类型[] 数组名=new 数据类型[数组长度];
(2)数据类型[] 数组名=new 数据类型[数组长度]{元素1,元素2…};
(3)数据类型[] 数组名=new 数据类型[]{元素1,元素2…};
静态初始化 → 数据类型[] 数组名={元素1,元素2…};
2.二维数组初始化

数据类型[,] 数组名 = new 数据类型[第一维长度,第二维长度];
  1. int[,] arr= new int[50,3];
复制代码
数据类型[,] 数组名 = new 数据类型[,]{数组值};
  1. int[,] arr= new int[,]{{1,0,1},{3,0,5}};
复制代码
数据类型[,] 数组名 = {数组值};
  1. int[,] arr= {{1,0,1},{3,0,5}};
复制代码


  • 二维数组的长度

  • 总长度(二维数组的元素个数)

    • array.Length

  • 第一维的长度

    • array.GetLength(0)

  • 第二维的长度

    • array.GetLength(1)

  1. for (int i = 0; i < heroData.GetLength(0); i++)
  2. {
  3.    for (int j = 0; j < heroData.GetLength(1); j++)
  4.    {
  5.        Console.Write(heroData[i,j] + "\t");
  6.    }
  7.    //换行
  8.    Console.WriteLine();
  9. }
复制代码
函数

  1. // <访问修饰符> <返回值类型> <函数名称> (参数列表)
  2. <Access Specifier> <Return Type> <Method Name>(Parameter List)
  3. {
  4.         // 函数主体
  5.    Method Body
  6. }
复制代码
访问权限修饰符


全部类型和类型成员都具有可访问型级别。该级别可以控制是否可以从你的程序集或其他程序集中的其他代码中利用它们。简单来说就是当前函数或属性的访问权限。
public 整个解决方案中访问。
protected internal 是protected 和 internal 的并集,符合任意一条都可以访问。
proteced 只允许在当前类内部以及该类的子类中访问。
internal 只能在当前项目中访问。在同一个项目中与 public 的权限划一。
private 只允许在本项目本类中被访问。
(1)如果没有主动利用访问修饰符,那么默认是private 私有的,外界是访问不到的。
修饰符类内部子类其他类public可以可以可以private可以不可以不可以protected可以可以不可以 参数通报

参数可以通过三种方式通报给函数:
值通报: 值通报会复制参数的现实值并赋值给函数的情势参数,实参和形参利用的是两个差别内存位置中的值,当形参的值发生改变时,不会影响实参的值,从而保证了实参数据的安全。
引用通报: 引用通报会复制参数的内存位置并通报给情势参数,当形参的值发生改变时,同时也会改变实参的值。
输出通报: 输出通报可以一次返回多个值
1.引用通报

引用通报是对变量内存位置的引用。与值通报差别,利用引用通报的情势通报参数时,并不会为形参创建新的内存所在,而是与实参共同指向雷同的内存所在。正因为云云,当修改形参的值时,实参的值也会被修改。
在 C# 中,需要利用 ref 关键字来利用引用通报:
  1. class Demo {
  2.    static void Main(string[] args) {
  3.       int num = 11;
  4.       Console.WriteLine("调用函数之前:{0}", num);
  5.       Func(ref num);
  6.       Console.WriteLine("调用函数之后:{0}", num);
  7.    }
  8.    public static void Func(ref int val){
  9.       val += val;
  10.       Console.WriteLine("函数内部的值:{0}", val);
  11.    }
  12. };
  13. // 输出
  14. // 调用函数之前:11
  15. // 函数内部的值:22
  16. // 调用函数之后:22
  17. // 通过运行结果可以看出,当函数内部值发生更改时,因为他们共用一个内存地址所以调用函数后值发出了改变
复制代码
2.输出通报

利用 return 语句可以从函数中返回一个值,但是利用输出通报则可以从函数中一次性返回多个值。输出通报与引用通报相似,差别之处在于输出通报是将数据从函数中传输出来而不是传输到函数中。
在 C# 中,需要利用 out 关键字来利用输出通报
  1. class Demo {
  2.    static void Main(string[] args) {
  3.       int num = 11;
  4.       Console.WriteLine("调用函数之前:{0}", num);
  5.       Func(out num);
  6.       Console.WriteLine("调用函数之后:{0}", num);
  7.    }
  8.    public static void Func(out int val){
  9.       val = 22;
  10.    }
  11. };
  12. // 输出
  13. // 调用函数之前:11
  14. // 调用函数之后:22
  15. // 通过运行结果可以看出,在函数体内直接更改了nun的值
复制代码
留意: 不可直接将参数举行运算,可以直接赋值。如果要举行算术运算则新建一个临时变量举行运算。
ref 不需要对实参赋值,就可以利用。out 需要对实参赋值后,才可以利用。
  1. public static void Func(out int val){
  2.     // 语法错误
  3.      val += 22;
  4.     // 正确
  5.     int temp = 11;
  6.     val = temp;
  7.     val += val;
  8. }
复制代码
 函数重载

(1)与返回值无关(2)与参数列表的个数有关(3)与参数列表的差别数据类型的序次有关
C#枚举

枚举是一组命名整型常量。枚举类型是利用 enum 关键字声明的。
C# 枚举是值类型。换句话说,枚举包含自己的值,且不能继承或通报继承
声明枚举的一般语法:
  1. enum <enum_name>
  2. {
  3.     enumeration list
  4. };
复制代码
此中,


  • enum_name指定枚举的类型名称
  • enumeration list是一个用逗号分隔的标识符列表。
枚举列表中的每个符号代表一个整数值,一个比它前面的符号大的整数值,默认情况下,第一个枚举符号的值是0,反面的比前面的加一,比方:
  1. enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
复制代码
  1. using System;
  2. namespace day01
  3. {
  4.    
  5.     class Program
  6.     {
  7.       enum Day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
  8.         static void Main(string[] args)
  9.         {
  10.             int x = (int)Day.Sun;
  11.             int y = (int)Day.Fri;
  12.             Console.WriteLine("Sun={0}\nFri={1}",x,y);
  13.            
  14.         }
  15.     }
  16. }
复制代码
枚举可以是任何数字数据类型,比方 byte,sbyte,short,ushort,int,uint,long 或 ulong。但是,枚举不能为字符串类型。
在 enum 名称后指定类型为:type。下面定义了字节 enum。
  1. enum Categories: byte
  2. {
  3.      Electronics = 1,  
  4.      Food = 5,
  5.      Automotive = 6,
  6.      Arts = 10,
  7.      BeautyCare = 11,
  8.      Fashion = 15
  9. }
复制代码
C#结构体


在 C# 中,结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。struct 关键字用于创建结构体。
结构体是用来代表一个记载。假设您想跟踪图书馆中书的动态。您可能想跟踪每本书的以部属性:
Title
Author
Subject
Book ID
定义结构体
为了定义一个结构体,您必须利用 struct 语句。struct 语句为程序定义了一个带有多个成员的新的数据类型。
比方,您可以按照如下的方式声明 Book 结构:
  1. struct Books
  2. {
  3.    public string title;
  4.    public string author;
  5.    public string subject;
  6.    public int book_id;
  7. };  
复制代码
  1. using System;
  2. using System.Text;
  3. namespace day01
  4. {
  5.    struct Books
  6.     {
  7.         public string title;
  8.         public string author;
  9.         public string subject;
  10.         public int book_id;
  11.     };
  12.     class Program
  13.     {
  14.      
  15.         static void Main(string[] args)
  16.         {
  17.             Books Book1;
  18.             Book1.title = "C programming";
  19.             Book1.author = "Nuha Ali";
  20.             Book1.subject = "C programming Tutorial";
  21.             Book1.book_id = 12345;
  22.             Console.WriteLine("Book1 title:{0}", Book1.title);
  23.             Console.WriteLine("Book1 author:{0}", Book1.author);
  24.             Console.WriteLine("Book1 subject:{0}", Book1.subject);
  25.             Console.WriteLine("Book1 book_id:{0}", Book1.book_id);
  26.             Console.ReadKey();
  27.            
  28.         }
  29.     }
  30. }
复制代码
结构体默认无参数构造函数,不可以表现声明,但是可以写有参数的构造函数。如果结构体存在有参数构造函数,必须在构造方法返回前,对结构体内的属性(变量)举行表现赋值。静态函数自己就是结构体属性,可以通过结构体调用,所以无需声明其修饰符。
静态(static)构造函数:(1)不允许出现访问修饰符(2)静态构造函数必须是无参的
静态构造函数执行机遇:(1)只有在调用结构体方法/函数时,才会被执行
静态变量:(1)静态变量的声明,数据类型/用户自定义的类型前面,需要加关键字 static(2)静态变量不归属于某个实例(一般是类的实例或者是结构体的变量),只归属于当前自身。
  1. struct masty
  2. {
  3.     public string strname;
  4.     public masty(string name)
  5.     {
  6.         strname = name;
  7.     }
  8.     public void showname()
  9.     {
  10.         Debug.Log(strname);
  11.     }
  12.     /*public*/ static masty{
  13.      }
  14.         
  15. }
复制代码
类(class)

类的定义:一个类由两种东西组成,成员变量(对象有哪些)和成员函数(对象做什么事)。
注:一个类可以有多个对象,这些对象都会做这个类所定义的动作(函数),但各自有差别的数据
成员变量:一个类中的对象所具有的变量。每一个对象有自己的变量。
成员函数:一个类中的方法。
类 对象名词 = new 类(),类的实例化。
静态的成员函数,只能操作静态的成员,不能操作非静态的的成员常量和函数。
构造函数

C#构造函数是一种特殊的成员函数,它主要用于为对象分配存储空间,对数据成员举行初始化.
构造函数的性质:
    (1)C#构造函数的名字必须与类同名;
    (2)C#构造函数没有返回类型,它可以带参数,也可以不带参数;
    (3)声明类对象时,系统自动调用构造函数,构造函数不能被显式调用;
    (4)C#构造函数可以重载,从而提供初始化类对象的差别方法;
    (5)若在声明时未定义构造函数,系统会自动生成默认的构造函数,此时构造函数的函数体为空.
  (6)如果构造函数是私有的private,那么在类的外部,无法对当前类举行实例化。
声明构造函数的要求:
(1)构造函数不能有返回类型,包括void
(2)构造函数的名称必须与类名雷同(所以构造函数每每利用形参)
   访问修饰符 类名 (参数列表)
  {
     语句块;
}
  析构函数

用于在对象被销毁时执行清理操作。它与构造函数相反,构造函数用于在对象创建时执行初始化操作。
固然c#(确切说CLR) 提供了一种新的内存管理机制----自动内存管理机制,资源的释放是可以通过“垃圾接纳器”自动完成的,一般不需要用户干预,但在有些特殊情况下还是需要用析构函数的,如在c#中非托管资源的释放。


  • 析构函数是用于释放资源和执行清理操作的特殊方法
  • 析构函数的名称与类名雷同,但前面加上一个波浪线(~)作为前缀
  • 析构函数在对象被销毁之前自动调用
  1. // 析构函数
  2. ~ClassName()
  3. {
  4.     // 析构函数的代码
  5. }
  6. // ~类名()
  7. //{
  8. //   语句块;
  9. //}
复制代码
面向对象

1.继承

继承就是子类继承父类的特征和活动,使得子类对象(实例)具有父类的属性和方法,或子类从父类继承方法,使得子类具有父类雷同的活动。


  • 子类继承父类,父类派生子类
  • 子类又叫派生类,父类又叫基类(超类)
  • 子类继承父类成员,也可以有自己独立的成员
构造函数:先执行父类的构造函数,再执行子类构造函数
析构函数:先执行子类的析构函数,再执行父类的
继承的方式

class 子类:父类
{
}


  1. class Animal
  2.     {
  3.         #region
  4.         public string Name { get; set; }//名字
  5.         public string Color { get; set; }//颜色
  6.         public string Kind { get; set; }//种类
  7.         public string Favorite { get; set; }//爱好
  8.         #endregion
  9.         //父类构造函数
  10.         public Animal() { }
  11.         public Animal(string name,string color,string kind)
  12.         {
  13.             this.Name = name;
  14.             this.Color = color;
  15.             this.Kind = kind;
  16.         }
  17.         //父类方法
  18.         public void Introduce()
  19.         {
  20.             string info = string.Format("我的名字叫{0},身穿{2}的衣服,我是{1},我爱吃{3}!", Name, Color, Kind, Favorite);
  21.             Console.WriteLine(info);
  22.         }
  23.     }
复制代码


  • this关键字
用来访问父类成员(当前类和父类的成员变量和函数)
  1. class Dog : Animal
  2.     {
  3.         public Dog() { }
  4.         public Dog(string name, string color, string kind, string favorite)
  5.         {
  6.             this.Name = name;
  7.             this.Color = color;
  8.             this.Kind = kind;
  9.             this.Favorite = favorite;
  10.         }
  11.     }
复制代码


  • base关键字
1.调用父类的构造函数
2.调用父类的属性和方法
只能是public / protected相关的
  1. class Cat:Animal
  2.     {
  3.         public Cat() { }
  4.         public Cat(string name,string color,string kind,string favorite)
  5.             :base(name,color,kind)//1.调用父类构造函数
  6.         {
  7.             this.Favorite = favorite;
  8.         }
  9.         //跳舞
  10.         public void Dancing()
  11.         {
  12.             base.Introduce();//2.调用父类方法
  13.             Console.WriteLine("下面我给大家表演《小猫迪斯科》,请大家鼓掌啊:>");
  14.         }
  15.     }
复制代码
子类方法的覆盖




  • 条件条件:父类中有一个public函数,子类中没有该函数
因为子类中并没有该函数,所以调用必是父类的


  • 条件条件:子类里已经有了该函数,父类里面也有该函数
此时,子类对象调用子类的该函数,父类对象调用父类的该函数
这种子类函数,可以称之为覆盖


  • 子类在书写该函数的时间,规范的写法应该是: → [访问修饰符] new 返回值类型 函数名(参数列表)
覆盖:子类也有该函数了,以后调用的时间就调用子类的该函数
  1. public class Person
  2. {
  3.     public string name;
  4.     public Person(string name)
  5.     {
  6.         this.name = name;
  7.         Console.WriteLine(name);
  8.     }
  9.     public void Say() //父类的函数
  10.     {
  11.         Console.WriteLine("你在干什么!");
  12.     }
  13. }
  14. public class Person1:Person
  15. {
  16.     public Person1(string name):base(name)
  17.     {
  18.     }
  19.     public new void Say() //覆盖掉父类的函数
  20.     {
  21.         Console.WriteLine("弄啥呢!");
  22.     }
  23. }
  24. public class Person2:Person1
  25. {
  26.     public Person2(string name) : base(name)
  27.     {
  28.     }
  29.     public new void Say() //覆盖掉父类的函数
  30.     {
  31.         Console.WriteLine("搞啥呢!");
  32.     }
  33. }
  34. static void Main(string[] args)
  35. {
  36.     Person p = new Person("1");
  37.     p.Say();
  38.     Person1 p1 = new Person1("2");
  39.     p1.Say();
  40.     Person2 p2 = new Person2("3");
  41.     p2.Say();
  42.     PersonFun(p2);
  43.     Console.ReadLine();
  44. }
  45. public static void PersonFun(Person person)
  46. {
  47.     person.Say();
  48. }
复制代码


子类方法的重写【表现出多态】




  • 如果父类想要子类可以重写该函数
那么父类的该函数必须是一个虚函数
[访问修饰符] virtual 返回值类型 函数名(参数列表)


  • 子类该怎么重写
[访问修饰符] override 返回值类型 函数名(参数列表)


  • 重写:把子类和父类的该函数都重新写了一遍,有的新的内容
此时,子类的对象,无论是不是转换成了父类的类型,都会执行重写后的该函数


  • 关于VS自动生成类重写函数
右键类名
点击快速修复或重构
点击生成重写
  1. public class Person
  2. {
  3.    public string name;
  4.    public Person()
  5.    {
  6.    }
  7.    public Person(string name)
  8.    {
  9.        this.name = name;
  10.    }
  11.    public virtual void Say()
  12.    {
  13.        Console.WriteLine("我是父类的方法");
  14.    }
  15. }
  16. public class Person1 : Person
  17. {
  18.    public Person1(string name)
  19.    {
  20.    }
  21.    public override void Say()
  22.    {
  23.        Console.WriteLine("我是字类的方法");
  24.    }
  25. }
  26. static void Main(string[] args)
  27. {
  28.    Person1 p1 = new Person1("我是字类");
  29.    p1.Say();
  30.    Person p = new Person1("我是父类");
  31.    p.Say();
  32.    Console.ReadLine();
  33. }
复制代码
2.封装

把一个或多个项目封闭在一个物理的或者逻辑的包中。
在面向对象程序设计方法论中,封装是为了防止对实现细节的访问
抽象和封装是面向对象程序设计的相关特性。抽象允许相关信息可视化,封装则使开辟者实现所需级别的抽象
  1. using System;
  2. namespace RectangleApplication
  3. {
  4.     class Rectangle
  5.     {
  6.         //成员变量
  7.         public double length;
  8.         public double width;
  9.         public double GetArea()
  10.         {
  11.             return length * width;
  12.         }
  13.         public void Display()
  14.         {
  15.             Console.WriteLine("长度: {0}", length);
  16.             Console.WriteLine("宽度: {0}", width);
  17.             Console.WriteLine("面积: {0}", GetArea());
  18.         }
  19.     }// Rectangle 结束
  20.     class ExecuteRectangle
  21.     {
  22.         static void Main(string[] args)
  23.         {
  24.             Rectangle r = new Rectangle();
  25.             r.length = 4.5;
  26.             r.width = 3.5;
  27.             r.Display();
  28.             Console.ReadLine();
  29.         }
  30.     }
  31. }
复制代码
  在上面的实例中,成员变量 length 和 width 被声明为 public,所以它们可以被函数 Main() 利用 Rectangle 类的实例 r 访问。
  成员函数 Display() 和 GetArea() 可以直接访问这些变量。
  成员函数 Display() 也被声明为 public,所以它也能被 Main() 利用 Rectangle 类的实例 r 访问。
  3.多态

多态性意味着有多重情势。在面向对象编程范式中,多态性每每表现为"一个接口,多个功能"。
多态性可以是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。
静态多态性(编译时)
在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为:


  • 函数重载
  • 运算符重载
动态多态性(运行时)
是通过 抽象类 和 虚方法 实现的。父类对象=子类实例对象 被允许的,当父类对象去调用虚函数时,会去检测子类有没有重写,若重写了,则调用子类重写后的函数。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

李优秀

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表