[关闭]
@dragonfive 2015-06-22T09:31:00.000000Z 字数 9842 阅读 825

c#学习笔记

c#编程


为知笔记Vim-Markdown插件
使用:
新建.md文件
选择vim编辑器编辑
输入Markdown内容
Ctrl-P切换实时预览
:w命令保存
特性:
Markdown语法高亮
实时预览(包括Mathjax公式)
Vim快捷键
代码折叠
同步滚动 2014.7.20

下面通过用c#的字符串和Hashtable类来实现一个简体字转繁体字的功能,然后分析一些c#的语法

源码

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace 简体字转繁体字
  9. {
  10. class Program
  11. {
  12. static void Main(string[] args)
  13. {
  14. string[] simpleStrs = File.ReadAllLines(@"E:\code\test\简体字.txt",Encoding.Default);
  15. string simpleStr = String.Join("", simpleStrs);
  16. string[] complexStrs = File.ReadAllLines(@"E:\code\test\繁体字.txt",Encoding.Default);
  17. string complexStr = String.Join("", complexStrs);
  18. //Console.WriteLine(complexStr);
  19. Hashtable transform=new Hashtable();
  20. for (int i = 0; i < simpleStr.Length; i++)
  21. {
  22. transform.Add(simpleStr[i], complexStr[i]);
  23. }
  24. Console.WriteLine("请输入一句话");
  25. string originalStr = Console.ReadLine();
  26. StringBuilder stb = new StringBuilder();
  27. for (int i = 0; i < originalStr.Length; i++)
  28. {
  29. if (transform.Contains(originalStr[i]))
  30. {
  31. stb.Append(transform[originalStr[i]]);
  32. }
  33. else
  34. {
  35. stb.Append(originalStr[i]);
  36. }
  37. }
  38. Console.WriteLine("转化为繁体字为:");
  39. Console.WriteLine(stb);
  40. Console.ReadKey();
  41. }
  42. }
  43. }

程序运行结果

clipboard.png

值类型和引用类型

区别:
1. 值类型和引用类型在内存上存储的地方不一样
2. 传递值类型和引用类型的时候,传递的方式不一样。
值类型:int、double、bool、struct、enum 等存储在栈中。
引用类型:string、自定义类等,应用类型的值存在堆中,在栈中存的是堆中的地址。
4. 字符串的不可变性:指的是堆里面的内容不可变,这种内容具有唯一性,所以如果你有很多个string都叫"abc",实际上"abc"在,栈里的内容可以变。
5. 即时窗口可以查看内存地址。
6. 如果是在想改变字符串中某个字符怎么办呢,首先将字符串转换为char类型的数组,这个数组存在栈区,调用ToCharArray();返回char类型数组,然后改变,然后调用string(char [])这个构造函数再产生一个新String;
7. 我们大量对字符串进行拼接赋值操作时,内存中会产生大量的垃圾,这是我们需要StringBuilder,

string的方法

函数名 作用
Equals() 比较字符串,第二个参数可设为StringComparison.OrdinalIgnoreCase
Split() 字符串分割,第一个参数可以是不需要的那些字符构成的数组, 第二个参数StringSplitOption.RemoveEmptyEntries 把空项移除,返回分割出来的字符串数组;可以用来处理Jeson数据等格式化数据;
IndexOf 字符串中第一次出现某个序列的位置
Trim() 去除字符串两边的空格
Join() 把字符串数组格式化为字符串

继承注意事项

继承构造函数 在子类构造函数的函数列表里只能写:base(,,)不能写:父类名(,,,)

当子类隐藏父类的成员方法,可以在返回类型前加关键字new 来隐藏从父类哪里继承来的成员,隐藏的后果是子类调用不到父类的成员;

集合

里氏转换:

就是子类对象可以赋值给父类引用(隐式转换),如果父类引用指向的是子类对象,可以把父类强行转换为子类(显式转换),当然用is或as可以判断是不是那种对象;
is : 判断类型,如果是的那就返回true 否则返回false;需测试没有关系的类之间的情况;
as: 进行强转,如果成功就返回转换得到的那个对象,失败就返回null;

ArrayList

是一个集合:我们主要用泛型类型,这个类型不怎么用了 Array 类型一定,然后长度可变;
表示添加单个数据,其实都是引用无所谓的啦。很多数据的一个集合,相对于数组有两大好处;类型可以不一样,长度可变。

函数名 作用
add(object) 可以放object的任意对象
addRange 添加集合的时候使用
clear 移除所有的元素
Remove 根据对象删除
RemoveAt 根据下标删除
RemoveRange 根据下标范围删除
Contains 判断是否包含指定的对象
sort 排序,有些不同类型的元素排序没有意义
Reverse 逆序
Insert 插入对象
InsertRange 插入一定范围的元素

有个Count属性和别的对象的Length属性是一样的。
size() Capacity属性表示已分配的容量 刚开始为4,然后每次扩大一倍。

Hashtable

是键值对集合;(table开头小写哦)
在键值对集合中,是根据键找值的,用键做下标; 用foreach循环来遍历键值对集合,;
hashtable里面有两个重要的属性一个是Keys是键的集合,一个是Values是值的集合。键只能出现一次,值可以出现很多次;

函数名 作用
Add(key,value) 在现有HashTable里面试图添加一个键值对
Contains(key) 在现有HashTable判断是否包含某个键
ContainsKey(key) 在现有HashTable判断是否包含某个键
ContainsValue(value) 在现有HashTable判断是否包含某个值

ContainsValue
添加键值对的时候可以使用Add,也可以使用ht[键]=值(调用insert); 可以使用Contains和ContainsKey来判断是否包含某个键,用ContainsValue判断是否包含某个值;

foreach

foreach的效率比for要低一点;

var

c#是一门强类型语言,在代码当中必须对每一个变量的类型有一个明确的定义;
var用于弱类型中,var根据值能够推断出来类型,object有个GetType可以获取这个对象的类型。隐式类型的局部变量必须初始化,var一般用在foreach里面

path

是静态类
在System.IO里面,

函数名 作用
GetFileName("文件的全路径") 获取当前文件的文件名
GetFileNameWithoutExtension 获得不包括扩展名的文件名
GetExtension 获得文件的扩展名
GetDirectoryName 获得当前文件夹的名字
GetFullPath 获取当前文件的全路径

string [] contents=File.ReadAllLines(path,Encoding.Default);
Directory.GetFiles(path,"*.txt");//第二个选项是正则表达式匹配;这个是Directory类的静态方法;这个返回的是带目录名的文件名
DirectoryInfo类的对象有一个GetFiles和EnumerateFiles的方法也可以,返回的是不带目录名的文件名;
DirectoryInfo类有另外的实例方法GetDirectory和EnumerateDirectory()可以获取子文件夹的信息;

Directory

静态类

方法名 作用
CreateDirectory() 创建文件夹
DeleteDirectory() 删除文件夹,第二个参数如果为false 则文件夹不空则会抛异常,true时无妨
Move(a,b) 剪切
GetFiles(path,format) 读取目录下的文件名,带路径
GetDirectory(path) 读取目录下的子目录,带路径

可以使用Path.GetFileName;出去路径;

DirectoryInfo类

不是静态的;

方法名 作用
GetFiles
EnumerateFiles
GetDirectory
EnumerateDirectory

File类

是静态类

方法名 作用
Create("") 根据目录试图创建一个文件,如果文件已存在截取内容为空
Delete("") 根据目录试图删除一个文件,如果文件不存在
Copy(源文件,目标文件) 复制源文件,试图粘贴到目标文件
move(源文件,目标文件) 移动一个文件到另一个地方
ReadAllBytes() 从文件中读取一个字节数组,默认是ANSY编码
Encoding.Default.GetString(字节数组) 把字节数组转换为字符串
Encoding.Default.GetBytes(字符串) 把字符串转换为字节数组
WriteAllBytes() 把字节数组写入文件里,默认是ANSY编码
ReadAllLines() 把文本中所有的行读入到一个字符串数组里,默认是utf-8格式
ReadAllText 把文本中所有的文字读入到一个字符串里,默认是utf-8格式
AppendAllLines 在后面添加行
AppendAllText 在后面添加文本

FileInfo类

不是静态类

readAllLines,ReadAllText 只能读取文本文件 ReadAllBytes 读取字节;

File类一下子只能读小文件,大文件要用文件流

编码格式

编码格式:UTF-8 GB2312 GBK ASCII Unicode(utf8 utf17 utf32)
c# 中default的是ANCII GB2323是简体中文。
Encoding.GetEncoding("GBK").GetString(字节数组);
18700465745
584743774@qq.com


--------------

list

泛型集合

常用方法

List list = new List();

方法名 作用
Add() 添加元素
AddRange 添加一个集合
ToArray() 将集合转数组

数组有个方法叫ToList(),可以将数组转成集合;

为什么用list 而不是ArrayList 或 Hashtable

装箱与拆箱
把值类型转哈U呢为引用类型叫装箱,把引用类型转换为值类型称为拆箱;
装箱和拆箱会是运行时的操作,会使程序运行时间长,而使用泛型集合在编译的时候生成的是指定的类型;
看两种类型是否发生了装箱或者拆箱,要看,这两种类型是否存在继承关系,有继承关系才有可能发生装箱操作;

类名 元素类型 是否发生拆装箱 运行时间
list 确定且唯一 比较短
ArrayList 不确定,可有很多种 时间长

Dictionary

有一种新的遍历方式

foreach(KeyValuePair kv in dic){}

文件流FileStream、StreamReader和StreamWriter

可以操作大文件;
FileStream 操作字节;可以操作任何类型的文件;
StreamReader和StreamWriter操作字符;

FileStream

方法名 作用 参数
FileStream() 创建FileStream对象 第一个是路径,第二个是文件模式FIleMode枚举,第三个数据模式FileAcess
Read() 分部分读取文件,返回实际读到的有效字节数,如果读得数量不是第三个参数指定的,就用空填充 第一个是存放的字节数组,表示从哪个地方往数组里放数组?,每次最多读多少
Write() 把字节数组写入 第一个参数是字节数组,第二个参数表示从哪个地方开始写入,第三个参数表述最多写多少
close(),dispose() 关闭流,释放流所占用的资源

FileMode OpenOrCreate , Append
FileAcess. Read 、Write、ReadWirte

将创建文件流对象的过程写在using当中,会自动帮助我们释放资源;

StreamReader和StreamWriter

可以用来读取格式化文本文件;
有ReadLine和Write WriteLine方法

多态

在父类方法前面加一个virtual 在子类方法前加一个override;子类不一定要重写这个方法

抽象类与抽象方法

抽象方法没有方法体;抽象方法一定要在抽象类里面,抽象类的方法不一定是抽象方法
当父类实现一个方法没有意义的时候,可以写成抽象方法; 直接非抽象子类也要用override,要求子类必须重写这个方法;;

alt shift F10 可以快速添加命名空间 和 快速实现父类的抽象方法
ctr R E 可以快速为字段生成属性;

c_sharp中的访问修饰符

internal

只能在当前程序集(项目)中像public 一样被访问,而在其他项目中即使被引入命名空间也不能被访问到;
在同一个项目中internal权限大于protected,在其他项目中 如果继承了带有protected属性的类 则protected大于internal

protected internal

protected + internal;

1)、能修饰类的访问修饰符:public 、internal(默认的);
继承的时候子类的访问权限不能高于父类的访问权限,就是说父类是internal的时候 子类不能是public

序列化与反序列化

这个可以直接把对象转化为二进制进行存储与通信;

部分类

partial

密封类

sealed类 不能被继承

接口

出现原因

由于继承的当根性,为了实现多重继承的特性,接口可以实现多态

意义

接口就是一个规范或能力,

语法

  1. public interface I********able
  2. {
  3. void ********();
  4. }

接口的方法不允许添加访问修饰符,默认就是public(类默认是private),不能实现(区别于抽象类),子类实现时不用override(不同于抽象类),不能写字段;可以写自动属性(与普通属性不同,get set不用实现)
自动属性(写的时候没有字段和方法体,那还能不能取值和赋值呢),编译器会帮你生成一个私有字段;
接口与接口之间可以继承,并且可以多重继承;
既继承类又继承接口 要把类写在前面。
面向接口编程

自动属性与属性

自动属性是什么

自动属性就是写的时候只写一个属性,并不写字段,一般情况下也不实现。主要用于接口中;

为什么要用自动属性

下面的程序一测试了一下在一般的类中使用自动属性的情况;发现编译器会在生成解决方案的时候会自动生成一个私有的字段,这个可以在一些反编译软件里都可以看到。在类中使用自动属性的目的就在于可以不用写字段了,但是问题又出现了,既然你自动属性里面没有什么实现,为什么不直接用一个public的字段呢,连set,get和一对花括号两个分号都省了呢?想了想大概是编程习惯的原因,人们习惯调用大写的属性,而不是小写的字段,用属性来保护字段,那么为什么不把字段大写呢,同样也是编程习惯问题,推荐字段写成小写,前面还有个下划线,编程习惯统一起来容易理解项目。

如果把自动字段实现一下会怎么样

用问题来驱动我们学习比较好,实现一下怎么样,会不会爆炸?我试了一下把程序一的自动属性Age实现了一下,发现必须同时实现get方法和set方法,如果只实现其中一个就会编译不通过,我猜实现set和get方法之后这个属性就不是一个属性了,只能是一个代码段,代码段里面有两个方法,因为实现之后反编译就没有自动生成字段。如果只实现一个另一个没有实现就会提示类不是抽象类什么的,不是抽象类就不能不实现方法,而又没有生成字段。说明这时候编译器认为这只是一个代码块了。

那么我们该怎么用自动属性呢。

有两个使用场景

1.在接口中定义,继承接口的类就可以用了。
2.当你有个字段不需要限制访问,你为了编程习惯又不想写成公有字段,同时你有懒得主动写那个字段名的时候,就使用自动属性吧。

接口怎么用自动属性;

在上面的使用场景中接口中是可以声明自动属性的,声明之后意味着继承接口的所有非抽象的子类都必须实现这个自动属性,抽象的子类就不用实现了。那么又不知道生成的字段叫什么名字,怎么实现呢,答案是并没有办法具体实现,只能按照接口的写法照抄一遍,这样看来接口中用自动属性并没有什么卵用。唯一的用户就是强制非抽象子类必须有这个属性,何必呢。在程序二里发现如果不实现,编译时不通过的。得出的结论是接口中还是不要用自动属性。那么自动属性的唯一作用就是在符合编程规范的同时懒一把。

程序一

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace _31_interface
  7. {
  8. class Program
  9. {
  10. static void Main(string[] args)
  11. {
  12. Person p = new Person();
  13. p.Name = "leifeng";
  14. p.Age = 10;
  15. Console.WriteLine("name is {0},age is {1}",p.Name,p.Age);
  16. Console.ReadKey();
  17. }
  18. }
  19. public class Person
  20. {
  21. public string Name
  22. {
  23. set;
  24. get;// { return "SB"; }
  25. }
  26. //Cannot write in this way,because this will cause dead ciculation;in Set and Get,we can not use auto properity;
  27. //so we would better not to fulfill the set and get method of properity;
  28. //so if we need not to limit the get and set method,we can use the auto properity, but why not use the public field;
  29. //So the conclusion is we can only use the auto properity in Interface;
  30. //what interests me is that we can not just fulfill one of the tow method;
  31. public int Age
  32. {
  33. set;
  34. get; { return 20; }
  35. }
  36. private char _gender;
  37. public char Gender
  38. {
  39. get { return _gender; }
  40. set { _gender = value; }
  41. }
  42. }
  43. }

程序二:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace _31_interface
  7. {
  8. public interface IRunable
  9. {
  10. int NumOfLegs
  11. {
  12. set;
  13. get;
  14. }
  15. void Fly();
  16. }
  17. public class Car:IRunable
  18. {
  19. public int NumOfLegs
  20. {
  21. get;
  22. set;
  23. }
  24. public void Fly()
  25. {
  26. Console.WriteLine("Car can run on the road!");
  27. }
  28. }
  29. class Program
  30. {
  31. static void Main(string[] args)
  32. {
  33. Console.ReadKey();
  34. }
  35. }
  36. }

多态的实现

虚方法实现多态:需要建父类的对象;
抽象类实现多态:能抽象出父类,不用实例化父类;
接口实现多态:不能抽象出父类

测试仓库添加具体货架可以不;
我觉得仓库更适合用Dictionary;

winform应用程序

wpf使用xml来写UI,只写UI

Form1.cs 和Form1.designer.cs 共同构成Form1类
查看设计器 可以从后台快速切换到UI层;

属性

Name:在后台获得前台的控件对象,需要使用Name属性;
Text:前台显示的内容
Anchor:表示控件哪个角相对位置定下来
backcolor:背景色
backgroundimage:背景图片
backgroundimageLayout:背景图的填充方式
ContexMenuStrip:右键菜单;在菜单工具栏中添加
cursor:鼠标类型
Visible:控件是否可见
Enable:空间是否可用;
FlatStyle
Location:控件的相对位置;

事件

注册事件:三种方式,F4点击事件,默认选中的事件可以三地双击;
触发事件:
MoveEnter:当把鼠标移动进去的时候

多窗体

在Main函数当中,创建的窗体对象,我们称之为这个窗体应用程序的主窗体,当你把主窗体关闭后,整个应用程序就关闭了。
form.show();显示窗体
form.Close()关闭;//试试dispose()
在不同窗体里传递详细用静态类传递消息;
form.load();方法里面表示在加载窗体的时候,可以在里面写代码//试一试show()

Random类

.next方法;

TextBox

多行显示;
属性:
WordWrap:换行,默认为ture;即可以换行;
ScrollBars:滚动条;
PasswordChar: 用这个char代替你输入的密码;
事件:
TextChanged();可以用来说明你的密码够不够复杂;

Label

用来显示文本;
属性
Text

timer:

属性:

interval:时间间隔;
方法:
Tick();

DateTime.Now

DateTime.Now.ToString();获取当前系统日期和时间;
DateTime.Now.Hour;

SoundPlayer

属性:
SoundLocation: 要播放的wav文件的目录;

单选框与多选框'

checkbox:多选框
radioButton:单选
属性:
checked:表明是否选中

groupbox容器 对单选框分组;

MDI窗体的设计

1、首先确定一个父窗体;
2、IsMdiContainer设为true,
3、MenuStrip是菜单栏;
4、MdiParent属性设置父窗体'
5、LayoutMdi();//排列子窗体;

PictureBox

属性
SizeMode:设置图片在框中怎样显示
FormFile(表明图片的来源);

WebBrowser 浏览器控件

属性:
url: 网址;

下拉选择器:ComboBox

属性:Items集合;(list)可以用add添加;
DropDownStyle:控制下拉框的外观样式;
SelectedIndex:
SelectedItem:只有这个ToString才能用
SelectedText:
SelectedValue:

事件:
SelectedIndexChanged;当前下拉框选中项目改变;

下拉选择器的组合;
前一个选定,后面的才知道范围;

ListBox

属性:
Items:内容

事件:
DoubleClick()双击事件;

石头剪刀布程序

实现界面与面向对象的编程,前端与后台相分离;
我们我后台逻辑写到类里面,这样尽量使得前台只是调用方;
当我们需要多次使用一个代码段的时候可以选择代码段,点重构。

对话框

方法:
showDialog()
常见对话框:
OpenFileDialog
属性:
Title:对话框标题;
MultiSelect可以多选
InitialDirectory:初始目录;
Filter:文件类型 如"文本文件|.txt|媒体文件|.wav|图片文件|*.jpg"
FileName:选择的文件路径:
FileNames:多选的文件路径们;

SaveFileDialog

ColorDialog:颜色对话框
Color:
FontDialog:字体对话框
Font:选中的字体

记事本应用程序

Menustrip:菜单栏

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注