C# 介绍

一. 一个简单的helloworld

using System;

class helloworld
{
	//静态方法可以在不引用特定对象的情况下运行,所以main是程序入口点
    static void Main()
      {
          Console.WriteLine("helloworld");
      }
}

写完的程序保存在hello.cs中,可以在vs的命令行执行csc hello.cs编译该程序,会生成一个hello.exe可执行程序集,然后.\hello.exe就会输出helloworld。

二. 程序结构

C#中的关键组织结构包括:程序、命名空间、类型、成员和程序集

  • 程序声明类型,类型包含成员,并被整理到命名空间中
  • 类型:包括类和接口
  • 成员:包括字段、方法、属性和事件
  • 编译完的C#程序会被打包到程序集中,扩展名为.exe或.dll
using System;
namespace Acme.Collections
{
    public class Stack
    {
        Entry top;
        public void push(object data)
        {
            top = new Entry(top,data);
        }
        public Object pop()
        {
            if (top == null) throw new InvalidOperationException();
            object result = top.data;
            top = top.next;
            return result;
        }

        class Entry
        {
            public Entry next;
            public object data;
            public Entry(Entry next, object data)
            {
                this.next = next;
                this.data = data;
            }
        }
    }
}

使用csc /t:library acme.cs编译成库(不含main入口点的代码),并生成acme.dll程序集。
程序集是包含代码和元数据的自描述功能单元,所以不用在C#中引入#include指令和头文件,只需要在编译时引用特定的程序集

下面程序使用了acme.dll中的Acme.Collections.Stack类

using System;
using Acme.Collections;

class Test
{
    static void Main()
    {
        Stack s = new Stack();
        s.push(1);
        s.push(2);
        s.push(3);
        Console.WriteLine(s.pop());
        Console.WriteLine(s.pop());
        Console.WriteLine(s.pop());
    }
}

test.cs和acme.dll可以用编译器的/r选项来引用程序集:csc /r:acme.dll test.cs,就可以生成test.exe可执行程序集,执行就可以输出3 2 1。

三. 类型和变量

在这里插入图片描述
C#的五个类别是用户可定义的类别:类类型、结构类型、接口类型、枚举类型和委托类型

  • 类类型:包括数据成员(字段)和函数成员(方法、属性),支持单一继承和多形性
  • 结构类型:包括数据成员和函数成员,值类型不需要堆分配,不支持用户指定的继承,均隐式继承object
  • 接口类型:定义公共函数成员,实现接口的类或结构必须提供接口函数成员的实现
  • 委托类型:对具有特定参数列表和返回类型的方法的使用。通过委托,可以将方法视为可分配给变量并可作为参数传递的实体,类似于函数指针,但比指针安全
  • 枚举类型:枚举类型的值集与基础类型的值集相同。
  • 类、结构、接口和委托都支持泛型,所以可以用其他类型参数化。

默认构造函数
所有值类型都隐式声明为默认构造函数的公共无参数实例构造函数,默认构造函数返回一个名为零初始化实例,该实例成为值类型的默认值:

  • 简单类型
    • 有无符号整型:默认值为0
    • char:`\x0000`
    • float:0.0f
    • double:0.0d
    • decimal:0.0m
    • bool:false
  • 枚举类型,默认值为0,转换为类型E
  • 结构类型:默认值是通过将所有值类型的字段设置为其默认值,并将所有引用类型字段设置为null生成的值
  • 可以为null的类型:默认值为HasValue属性为false且value属性未定义的实例。

值类型的默认构造函数使用new运算符进行调用,不会产生构造函数的调用

允许结构类型声明参数化实例构造函数,

每种C#类型都直接或间接地派生自object类类型,object是所有类型的最终基类。只需将值视为object,即可将引用类型的值视为对象,通过执行装箱或取消装箱操作,值类型的值被视为对象。值类型的值通过执行装箱和取消装箱的操作被视为对象。

using System;

class Test
{
    static void Main()
    {
        int i = 123;
        //int -> object
        object o = i;
        //object -> int
        int j = (int)i;
    }
}

在C#中,将零整数或浮点值转为布尔值,通过将整数或浮点值与零相比较来实现,或通过将对象引用显式比较为null来实现。

四. 表达式

在这里插入图片描述

  • 可重载的一元运算符:+,-,!,~,++,–,true,false
  • 可重载的二元运算符:+,-,*,/,%,&,|,^,<<,>>,==,!=,>,<,>=,<=
  • 无法重载成员访问、方法调用、=、&&、||、??、?、=>、checked、unchecked、new、typeof、default、as和is

1. f(x)

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Caculator c = new Caculator();
            //委托:不用去直接做这个事情,通过委托间接的调用一个方法
            Action action = new Action(c.PrintHello);
            action();
        }
    }
    class Caculator
    {
        public void PrintHello()
        {
            Console.WriteLine("hello");
        }
    }
}

2. []

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            // 泛型:泛型类本身不是一个完整的类,需要和其他类型组合在一起称为一个完整的类。
            Dictionary<string, Student> stuDic = new Dictionary<string, Student>(); 
            for(int i = 0; i < 100; i++)
            {
                Student student = new Student();
                student.Name = "S_" + i.ToString();
                student.Score = 100 + i;
                stuDic.Add(student.Name, student);
            }
            Student student6 = stuDic["S_6"];
            Console.WriteLine(student6.Score);
        }
    }
    class Student
    {
        public string Name;
        public int Score;
    }
}

3. typeof

typeof帮助我们查看一个类型的内部结构,类型的内部结构术语叫Metadata,里面包含这个类型的基本信息,比如:什么名字、属于的名词空间、父类、包含的方法和属性。等成员拿到这些信息后就可以根据这些信息决定自己的程序逻辑。

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Type t = typeof(int);
            Console.WriteLine(t.FullName);
            Console.WriteLine(t.Name);
            Console.WriteLine(t.Namespace);
            int c = t.GetMethods().Length;
            foreach(var mi in t.GetMethods())
            {
                Console.WriteLine(mi.Name);
            }
            Console.WriteLine(c) ;
        }
    }
}

4. default

帮助获取一个类型的默认值

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            // 结构体类型
            int x = default(int);
            Console.WriteLine(x);
            // 引用类型
            Form form = default(Form);
            Console.WriteLine(form==null);
            //枚举类型
            Level level = default(Level);
            Console.WriteLine(level);
        }
    }
    enum Level
    {
        Low,
        Mid,
        High
    }
}

5. new

在这里插入图片描述
new可以调用示例的初始化器

Form form = new Form() { Text = "hello", FormBorderStyle = FormBorderStyle.SizableToolWindow};
form.ShowDialog();

//new和var组合:为匿名类型创建对象,并用隐式类型变量引用这个实例
var person = new{Name = "je", Age = 34};
Console.WriteLine(person.GetType().Name); // <>f__AnonymousType0`2

new还是关键字

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu = new Student();
            stu.Report();
            CsStudent cs = new CsStudent();
            cs.Report();
        }
    }
    class Student
    {
        public void Report()
        {
            Console.WriteLine("I'm a student.");
        }
    }
    class CsStudent: Student
    {
        //子类把父类的方法隐藏了
        new public void Report()
        {
            Console.WriteLine("I'm a Csstudent.");
        }
    }
}

6. checked和unchecked

C#默认采用unchecked

checked:编辑器要检查程序有没有溢出

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            uint x = uint.MaxValue;
            Console.WriteLine(x);
            string binStr = Convert.ToString(x, 2);
            Console.WriteLine(binStr);
            
            //法一
            try
            {
                uint y = checked(x + 1);
                Console.WriteLine(y);
            }
            catch (OverflowException ex)
            {

                Console.WriteLine("there is overflow!");
            }
            //法二
            checked
            {
                try
                {
                    uint y = x + 1;
                    Console.WriteLine(y);
                }
                catch (OverflowException ex)
                {

                    Console.WriteLine("there is overflow!");
                }
            }
        }
    }
}

7. sizeof

sizeof只能用来获取结构体数据类型的实例在内存中的字节数,string和object不是结构体

在默认情况下,可以获取自定义数据类型的字节数,但是需要放在不安全的上下文中
在这里插入图片描述

8. 移位

在这里插入图片描述
右移:如果是整数补0,如果是负数补1

9. is和as

x is T:如果x是T,则返回true,否则返回false
x as T:类型转换,返回类型为T的x,如果x的类型不是T,则返回null

10. null合并

class Program
{
    static void Main(string[] args)
    {
        int? x = null;
        //如果x为null,则y的值为1,否则为x
        int y = x ?? 1;
        Console.WriteLine(y);
    }
}

五. 语句

foreach语句

 static void Main(string[] args)
 {
     foreach(string s in args)
     {
         Console.WriteLine(s);
     }
 }

yield语句

foreach (int i in ProduceEvenNumbers(9))
{
    Console.Write(i);
    Console.Write(" ");
}
// Output: 0 2 4 6 8
IEnumerable<int> ProduceEvenNumbers(int upto)
{
    for (int i = 0; i <= upto; i += 2)
    {
    	//在迭代中,提供下一个值
        yield return i;
    }
}
Console.WriteLine(string.Join(" ", TakeWhilePositive(new int[] {2, 3, 4, 5, -1, 3, 4})));
// Output: 2 3 4 5

Console.WriteLine(string.Join(" ", TakeWhilePositive(new int[] {9, 8, 7})));
// Output: 9 8 7

IEnumerable<int> TakeWhilePositive(IEnumerable<int> numbers)
{
    foreach (int n in numbers)
    {
        if (n > 0)
        {
            yield return n;
        }
        else
        {
        	//显示迭代结束
            yield break;
        }
    }
}

六. 类和对象

1. 可访问性

在这里插入图片描述

2. 类型参数

class Test
{
    static void Main(){
    	//使用泛型类时,必须为每个类型参数提供类型自变量
        Pair<int,string> pair = new Pair<int, string> { First = 1, Second = "two" };
        int i = pair.First;
        string s = pair.Second;
    }
    //pair的类型参数是TFirst和TSecond
    public class Pair<TFirst, TSecond>
    {
        public TFirst First;
        public TSecond Second;
    }
}

3. 基类和派生类

	//Point的基类是object
   public class Point
    {
        public int x, y;

        public Point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }
    //Point3D的基类是Point
    public class Point3D : Point
    {
        public int z;
        public Point3D(int x, int y,int z)
            :base(x, y)
        {
            this.z = z;
        }
    }
    //类类型的变量可以引用相应类的实例或任意派生类的实例
    Point a = new Point(10,10);
    Point b = new Point3D(10,10,20);

类继承基类的所有成员(实例和静态构造函数除外)和析构函数。
类类型的变量可以引用相应类的实例或任意派生类的实例。

4. 字段

  • 字段是一种表示与对象或类型(类与结构体)关联的变量,也叫成员变量。与对象关联的字段称为实例字段;与类型关联的字段称为静态字段,由static修饰
  • 无显示初始化时,字段获得其类型的默认值,所以字段永远不会未被初始化
  • 实例字段初始化的时机:对象创建时;静态字段初始化的时机:类型被加载时
  • 只读字段readonly

5. 方法

静态方法(用static修饰)通过类访问,只能直接访问静态成员
实例方法通过类实例访问,能够访问静态和实例成员

6. 参数

  • 值参数:修改值参数不会影响为其传递的自变量
    • 值类型
      在这里插入图片描述

    • 引用类型,并且创建新对象
      在这里插入图片描述

    • 引用类型,只操作对象,不创建新对象
      在这里插入图片描述

  • 引用参数:用ref修饰,引用参数指的存储位置与自变量相同,必须对自变量进行明确赋值,用于需要修改实际参数值的场景
  • 输出参数:用out修饰,与引用参数类似,调用方提供的自变量的初始值不重要,用于出返回值外还需要输出的场景
  • 数组参数:用params修饰,参数数组只能是方法的最后一个参数
class Test
{
    static void Main(string[] args)
    {
        int res = CaculateSum(1,2,3);
        Console.WriteLine(res);
    }
    static int CaculateSum(params int[] arr)
    {
        int sum = 0;
        foreach (int i in arr)
        {
            sum += i;
        }
        return sum;
    }
}
  • 具名参数:提高代码的可读性,参数位置不再受参数列表设计的约束
static void Main(string[] args)
{
    PrintInfo(name: "tom", age: 12);
}
static void PrintInfo(string name, int age)
{
    Console.WriteLine("Hello {0},you are {1}", name, age);
}

7. 扩展方法(this参数)

不修改目标数据类型源码的情况下为目标数据类型“追加”方法

  • 方法必须是共有的、静态的,即被public static修饰
  • 必须是形参列表中的第一个,由this修饰
  • 必须由一个静态类(一般类名为SomeTypeExtension)来统一收纳SomeType类型的扩展方法
class Test
{
    static void Main(string[] args)
    {
        double x = 3.1415926;
        Console.WriteLine(x.Round(2));
    }
}
static class RoundExtension
{
    public static double Round(this double x, int digits)
    {
        double res = Math.Round(x, digits);
        return res;
    }
}

Linq扩展方法

using System;
using System.Collections.Generic;
using System.Linq;

class Test
{
    static void Main(string[] args)
    {
        List<int> list = new List<int>() { 3, 12, 14, 15 };
        bool res = list.All(i => i > 10);
        Console.WriteLine(res);
    }
}

8. 虚方法、重写方法、抽象方法和方法重载

  • 虚方法:用virtual修饰,调用虚方法时,为其调用方法的实例运行时类型决定了要调用的实际方法实现代码
  • 重写方法:可以在派生类中重写虚方法,当实例方法中包含override时,该方法将重写具有相同签名的继承的虚方法
  • 抽象方法:无实现的虚方法,abstract修饰,只允许在也声明abstract的类中使用,必须在所有非抽象派生类中重写抽象方法。抽象类专门作为基类来使用,具有解耦功能。
  • 方法重载:同一类中可以有多个同名方法,只要这些方法具有唯一签名即可

9. 属性

属性是一种用于访问对象或类型的特征的成员,特征反映了状态。属性是字段的自然扩展。
ctrl + e+r自动生成属性或者右键->Refactor->Encapsulate Field->可以修改你想要的属性的名称->Okay

class Test
{
    private int age;
    public int Age
    {
        get { return age; }
        set
        {
            if (value > 0 && value <= 120)
            {
                age = value;
            }
            else
            {
                throw new Exception("Age value has error");
            }
        }
    } 
}

10. 索引器

索引器使对象能够用与数组相同的方式(即使用下标)进行索引。
索引器可以重载。
在这里插入图片描述

11. 默认值

以下类别的变量会自动初始化为其默认值

  • 静态变量
  • 类实例的实例变量
  • 数组元素

六. 结构

借助类,两个变量可以引用同一个对象,对一个变量执行的运算可能会影响另一个变量引用的对象;借助结构,每个变量都有自己的数据副本,对一个变量执行的运算不会影响另一个变量。

Point a = new Point(10, 10);
Point b = a;
a.x = 20;
//若Point为类,输出20,Point为结构,输出10
Console.WriteLine(b.x);

七. 数组

数组是引用类型,声明数组变量只是为引用数组实例预留空间,实际的数组实例是在运行时使用new创建。

C#允许"@"字符作为前缀以使关键字能够作为标识符

八. vs使用技巧

鼠标放在空行,右键单击并选择快速操作和重构菜单,就可以生成构造函数之类的。

ctrl+k+d:调整格式

ctrl + d:复制当前行到下一行

  • 14
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值