说明
c和c++的学习终于要告一段落了,虽然不知道什么时候开学,但是比赛还是要准备一下的,所以复习一下c#先。下面的代码是跟来自程序员的暴击上课的时候顺面打的,和他的例子不完全一样,我把所有程序都写在了一个项目中,并且用c#的region划分隐藏(这个功能实在太好用了)这样比程序的自动划分更灵活,可以做到按知识点划分。
效果如下:
文件目录
重要知识点
堆栈:
1.堆对应的是内存,栈对应的是运行内存
2.值类型(int,double,float,bool,char,struct,enum)存储在栈上,引用类型(string,数组)存储在堆上
3.栈中存储了引用类型的引用地址
4.栈上数据在重复赋值的时候被覆盖,堆上数据则会继续在堆上开辟而栈上地址,旧数据不会被覆盖或清除,而会变为垃圾,因此要gc清除,
静态成员使用必须要类名去调用,而实例成员使用对象名调用,静态函数中只能访问静态成员,不能访问实例成员,而实例函数则随便
继承:
1.子类继承父类的公开字段\属性和方法,但是没有继承父类的私有字段,构造函数
2.子类默认调用父类无参数的构造函数,但是若父类重写一个有参的构造函数之后会被覆盖
里氏转化:
1.子类可以用父类成员,而父类不可以用子类的
2.子类对象可以直接赋值给父类对象
3.如果父类对象装的是子类对象,则父类对象可以强制转化为子类
//object类是终极积累,是所有类型的父类,可以强制转化为其他类,其中集合(arraylist)就是object类的
集合长度问题:
1.count表示实际包含元素个数 capcity表示可以包含元素个数
2.每次集合count值超过capcity值时就会多开辟一倍的空间来保证集合的长度一直够用
拆装箱:
1.只有存在继承关系才会发生拆箱装箱
2.装箱:别的类型转化为object类型时
3.拆箱:object类型转化为别的类型
多态:
1.抽象类里不一定有抽象方法但是抽象方法一定要在抽象类之中,抽象类不能写方法体
2.虚方法:父类里的方法用virtual声明
3.接口:可以有返回值,不允许加访问修饰符(默认public),不能写方法体,不能写字段,只能写自动属性,不能实例和抽象类一样可以继承接口,且可以多继承,不能继承类,
4.一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类并实现了接口,那么语法上父类要写在接口前面
//实现多态的情景
5.知道父类的方法怎么写,并且还要创建父类对象的时候用虚方法
6.几个类中能提取出一个父类并且父类必须写上几个子类共有的方法但是还不知道怎么写这个方法的时候用抽象类
7.几个类提取不出父类,但是几个类都有一个共同的行为和能力就用接口
访问修饰符:
1.public:可以被别的项目访问
2.private:只能再当前类内部访问
3.protected:只能再类的内部以及该类的子类中访问
4.internal(类默认): 解决方案资源管理器里面右键引用-添加引用-项目-点击 还要再命名空间using对应项目名
5.protected internal:protected+internal
6.能够修饰类的访问修饰符只有:public internal
代码
program
using System; //引用命名空间
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1 //命名空间用于解决类的重名问题
{
//f11单步执行 f10单步跳过 f5调试 f9设置断点
//alt+shift+上下键可以多行选择
//alt+上下可以快速移动语句
//ctrl+f 查找,f3查找下一个
//ctrl+左右backspace 可以一个单词一个单词的操作
struct Books//结构体不可以赋初值,类可以;
{
public string title;
public string author;
public int book_id;
public void ReadBooks()
{
Console.WriteLine("reading......");
}
};
enum Week
{
Sun,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat
}
class Program
{
static void Main(string[] args)
{
//数据类型//
#region
int a = 1;
float b = 0.1f;//单精度浮点数后面要加一个f,双精度不用
double c = 0.1;
//数组定义及初始化/
double[] balance = new double[10];
balance[0] = 4500.0;
int[] number = new int[5];//数据类型[维度,默认为1] 数组名=new 数据类型[数组长度];
int[] age = { 0, 1, 2, 3, 4, 5 };
number[0] = 1;
number[4] = 5;//最大到4;
//循环语句的i作用域为循环体内
for (int i = 0; i < number.Length; i++)//数值可以视为一个对象,length时他的长度属性
{
number[i] = i;
}
int[] mark = new int[5] { 1, 2, 33, 4, 45 };//长度必须匹配
int[] marks = new int[] { 99, 98, 92, 97, 95 };//可以不预设长度
int[] score = marks;//可以赋值一个数组变量到另一个目标数组变量中。在这种情况下,目标和源会指向相同的内存位置
string[] name = new string[4];//初始值是Null,Null和空不一样,Null没有开辟空间,空则开辟了空间
bool[] boo = new bool[10];//初始值为false
#endregion
//输入/
#region
//string e = Console.ReadLine();//必须是string
//int f = Console.Read();//必须是int
#endregion
//字符串/
#region
string str1 = "Miss Deng";//字符串重复赋值旧值不会销毁,重新开辟一块空间
string str2 = Console.ReadLine();
string str3;
str2 = str1.ToLower();
str3 = str1.ToUpper();
str2 = str1.ToLowerInvariant();//小写
str3 = str1.ToUpperInvariant();
if (str1.Equals(str2))//返回值为布尔类型,不区分大小写,而str1==str2区分大小写
{
Console.WriteLine("we are same");
}
if (str1.Contains("Deng"))
{
str1 = str1.Replace("Deng", "Long");
}
else
{
str1 = str1.Replace("Miss", "Mr");
}
a = str1.IndexOf("s");//索引第一个s在哪,没找到返回-1
b = str1.LastIndexOf("s");//索引最后一个
bool bo = str1.StartsWith("Mis");//判断是否以...开头,返回布尔类型 还有EndWith()
string str4 = "+ -a_.,dffg";
char[] aList = { '+', '-', '_', '.', ' ' };
string[] str5 = str4.Split(aList,StringSplitOptions.RemoveEmptyEntries);//返回一个数组
//split删掉的东西变为空,若想去除,则填后面的参数,重载有提示
str4 = str4.Substring(5,2);//自己体会输出数substring(0)截了等于没截
string str6 = " skdj ";
str6 = str6.Trim();//删除空格,派生的方法还有TrimStart() TrimEnd()
if (string.IsNullOrEmpty(str1))//判断是不是空,注意格式
{
Console.WriteLine("yes");
}
//计时
StringBuilder sb = new StringBuilder();
//string str7 = null;
Stopwatch sw = new Stopwatch();//要using .....
sw.Start();
for (int i=0; i < 10000; i++)
{
//str7 += i;//string和数组是引用类型 重复赋值要开辟空间,消耗时间多
sb.Append(i);//追加数据
}
sw.Stop();
Console.WriteLine(sb.ToString());//转化为字符串
sb.Clear();//清空
Console.WriteLine(sw.Elapsed);
string stri = string.Join("|", new string[] { "1", "2", "3" });//加入|到123之间,输出结果为1|2|3
#endregion
//输出 循环
#region
for (int i = 0; i < 7; i++)//ctrl+k+s快捷键创建特殊语句
{
Console.Write("i said:");//不换行
Console.WriteLine("Hello world!");//换行
Console.WriteLine();//换行
Console.WriteLine("wowo{0},askhk {1} skh {2} skdhwiu {3}",a,b,c,mark[1]);
Console.WriteLine("wowo "+a+",askhk "+b+" skh "+c+" skdhwiu "+mark[1]);//上下等价,只要又一边是字符串+就是连接的作用
}
#endregion
//枚举类型,给整数起别名///
#region
int x = (int)Week.Sun;//将枚举类型强制转化为整数类型
Console.WriteLine("Sun = {0}", x);
#endregion
//结构体,等价于自定义的类型,不能用new来创建,是值类型/
#region
Books bookOne;
bookOne.author = "zarro";
bookOne.title = "how to write a bug";
bookOne.book_id = 250;
bookOne.ReadBooks();
#endregion
//面向对象,引用类型//
#region
//初始化及修改字段
#region
//不用构造函数的实例方法>>>>>>>>>>>>????
//People zarro = new People();//一号男嘉宾
//zarro._name = "haha";
//zarro._gender = '男';
//zarro._age = 18;
//zarro.Hobby();
修改属性,以及简便的实例化类
//People dnils = new People()//二号男嘉宾
//{
// //Name等是属性,可以保护字段,使字段取值可控,通过修改属性间接修改字段
// Name = "hehe",//注意这是,
// Gender = '男',
// Age = 19//最后一个加不加都无所谓
//};//注意这里要加一个分号
//使用`构造函数的实力方法>>>>>>>>>>>????
People zarro = new People("haha", 18, '男');//一号男嘉宾
People dnils = new People("hehe", 19, '男');//二号男嘉宾
#endregion
//里氏转化
#region
//子类对象可以直接赋值给父类
People p = new ChinesePeople("haha",3,'男',250);//然而p没有iq这个属性但是还要赋值,然而下面强制转化后还会出现
Console.WriteLine(stri);
ChinesePeople hehe = (ChinesePeople)p;//被子类赋值过的父类对象可以强制转化为子类对象
Console.WriteLine(hehe.Iq);//强制转化之后q,也就是现在的hehe有了iq这一个属性
//is和as
//is:返回bool类型
People haha = new People("aa",12,'W');
if (haha is ChinesePeople)
{
Console.WriteLine("转化成功");
}
else
{
Console.WriteLine("转化失败");
}
//as:转化成功返回对应对象,失败返回null
ChinesePeople peo = haha as ChinesePeople;//haha(原本为People类型)转化为ChinesePeople类型的peo中
//以上两个转化都不可以成功,应为对象haha里面装的不是父类的变量
#endregion
//多态
//虚方法,用在父类
ChinesePeople cp = new ChinesePeople("anny",11,'a',213);
cp.SayHi();//子类的sayhi()
EnglishPeople ep = new EnglishPeople("啊龙", 12, 'b', 123);
People[] per = { cp, ep };
for (int i = 0; i < per.Length; i++)
{
per[i].SayHi();//因为存到了父类的列表里所以都是父类的sayhi(),除非sayhi()的new改为virtual
//利用判断的方法有点麻烦
//if(per[i] is ChinesePeople)
//{
//((ChinesePeople)per[i]).SayHi();//方法优先级高于强制转化,记得加括号
//}
//if (per[i] is EnglishPeople)
//{
//((EnglishPeople)per[i]).SayHi();
//}
}
//抽象类,不能被实例化,不知如何实现的时候可以用抽象类
Animal an = new Dog();//实例化抽象类的子类,抽象类的方法时没有方法体的,必须重写
an.Eat();//狗的Eat()
//接口
IGameMaker game = new Ali();
game.Gamemaker();//因为类里面写了显示实现接口,所有这里调用的是显式实现接口,否则调用的是类的定义的方法
Ali aa = new Ali();
aa.Gamemaker();//调用的是类里定义的同名方法
#endregion
//集合,任意长度,任意数据类型搭配/
#region
ArrayList list = new ArrayList();//非静态类,要创建实例
list.Add(true);
list.Add(123);
list.Add(0.123);
list.Add('a');
list.Add("asdkjhk");
list.Add(23.1f);
list.AddRange(list);//添加自己,注意,执行到这一行的时候list还不包含下面的数组
list.AddRange(new int[] { 1, 2, 3, 4, 5 });//数组等集合类型用addrange
for(int i =0;i < list.Count; i++)//count表示实际包含元素个数 capcity表示可以包含元素个数
{
Console.WriteLine(list[i]);//输出一此空一行,数组每个元素占一行
}
list.Clear();//清空所有
list.Remove(true);
list.RemoveAt(2);//删除第三个
list.RemoveRange(0,3);//包含第零个一共删除三个
//list.Sort();//升序排列,同一类型可以排
list.Reverse();//反序
list.Insert(0,'a');//插入一个,原来的后退
list.InsertRange(0, new int[] { 1, 2, 3 });//插入多个
bool booo =list.Contains('a');//判断是否包含
Random r = new Random();
//r.Next();//看重载提示
//练习,创建长为10随机但是互不相同的集合
#region
for (int i = 0; i < 10; i++)
{
int rNum = r.Next(0, 10);
if (!list.Contains(rNum))
{
list.Add(rNum);
}
else
{
i--;
}
}
for (int i = 0; i < list.Count; i++)
{
Console.WriteLine(list[i]);
}
#endregion
//泛型集合,同一类型但是任意长度的集合
List<int> li = new List<int>();//小括号
li.Add(1);
li.AddRange(new int[] { 2, 3, 4, 56, 7 });
//泛型和数组可以互相转化
int[] Num = li.ToArray();
List<int> list2 = Num.ToList();
#endregion
//函数|方法//
#region
int one = 0;
int two = 0;
int sum = 0;
string q;
int avg = 0;
Program.Sum(out one, out two, out sum, out avg, out q);//执行完毕之后one two sum avg的值都改变了
ZiZeng(ref one);
ZiZeng(ref one, ref two);//函数重载,同一个函数名不同参数列表(类别,数量)
//常见的函数重载有Console.WriteLine();
#endregion
Console.ReadKey();//等待任意键退出
}
//函数定义/
#region
//public static 返回值类型(void) 帕斯卡函数名(参数列表:参数类型 参数名) {
// 函数代码体
// return 返回值;
//}//public:访问修饰符,公开的,哪里都可以访问到 static:静态标识符
//方法调用:类.方法名(参数);同一个类中类名可以省略
public static void Sum(out int a, out int b,out int sum,out int avg,out string i)
{
a = 5;//out和ref是传参数,return是传值,也就是说Sum前面的void(返回值类型)和后面的参数类型没有半毛钱关系
b = a + 1;
sum = a + b;
avg = sum / 2;
i = "hahaha";
}
public static void ZiZeng(ref int s)//把参数带进来再带出去;
{
s += 3;
}
public static void ZiZeng(ref int s,ref int x)
{
s += 3;
x += 3;
}
#endregion
}
}
people
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
//类名 对象名 = new 类名();
//赋值
public class People //访问修饰符有三种public公开易改 protect private只能在类里面访问
{
People()//析构函数,和类名同名,程序结束的时候才会被执行,作用:释放资源,垃圾回收器
{
Console.WriteLine("sakjnk");//GC
}//现阶段少用
public People(string name,int age,char gender)//构造函数,名字和类名一样1,不能加void,没有返回值,创建对象的时候先会执行,可以重载
{
this.Name = name;
this.Age = age;
this.Gender = gender;
}
public string _name;//公开字段,变量前面最好加上一个_
public int _age;
public char _gender;
//private可以限定输入输出
//下面三个使被保护的字段
private string _name1;//私有字段不能被继承
private int _age1;
private char _gender1;
public string Name//这是属性,里面的_name1是属性对应可修改的字段
{
//set和get本质是函数
get { return _name1; }//当通过属性名取值的时候,会自动调用get中的代码
set { _name1 = value; }//当通过属性名給字段赋值的时候,会自动调用set中的代码 value是关键字,代表赋给属性的值
}//这段代码写不写无所谓因为这是默认
public int Age
{
get { return _age1; }
set
{
if (value < 0 || value > 100)
{
value = 0;
}
else
{
_age1 = value;
}
}
}
public char Gender
{
get
{
if (_gender1 == '男' || _gender1 == '女')
{
return _gender1;
}
else
{
return _gender1 = '妖';
}
}
set { _gender1 = value; }
}
public virtual void Hobby()//只有虚方法子类才可以重写
{
Console.WriteLine("I like to write bug.");
}
//标记为虚方法
public virtual void SayHi()//可以使父类的同名方法调用子类的方法(当子类在子类数组或集合(父类型)时)
{
Console.WriteLine("i am a human");
}
}
}
EnglishPeople
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class EnglishPeople:People
{
public EnglishPeople(string name, int age, char gender, int iq)
: base(name, age, gender)
{
this.Iq = iq;
}
private int _iq;
public int Iq { get => _iq; set => _iq = value; } //表达式主体表示方法,可按灯泡自行转化
public void ToDo()
{
Console.WriteLine("我来自外国");
}
public new void SayHi()
{
Console.WriteLine("我是歪果仁");
}
public override void Hobby()
{
Console.WriteLine("i eat apple ");
}
}
}
ChinsesPeople
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
public class ChinesePeople : People //继承
{
public ChinesePeople(string name, int age, char gender, int iq)//没有继承父类的构造函数,要特此声明然后才能用构造函数
: base(name,age,gender)
{
this.Iq = iq;
}
private int _iq;//crtl+re快捷键
public int Iq { get => _iq; set => _iq = value; }
public void ToDo()
{
Console.WriteLine("i am from chinese");
}
public new void SayHi()//new,隐藏父类同名的方法
{
Console.WriteLine("i is some humen");
}
}
}
Animal
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
abstract class Animal//抽象类
{
public abstract void Eat();//抽象方法
public void run()
{
//空实现
}
}
}
dog和rabbit差不多一样,不重复写了
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Dog:Animal
{
public override void Eat()
{
Console.WriteLine("i like bone");
}
}
}
学过c++之后再复习c#发现亲切了许多。