三种项目类型
dos => 控制台应用程序
c/s => 窗体应用程序
b/s => net应用程序
C#基本结构和语法
//用字符插入
using System
namespace HelloApplication
{
static void Main(string[] agrs)
{
class Helloworld
{
var name = "amy";
Console.WriteLine($"Hello {name}!"); //**$和引号之间不能有空格**
}
}
}
//内插字符串
public class Vegetable
{
public Vegetable(string name) => Name = name;
public string Name { get; }
public override string ToString() => Name;
}
public class Example
{
public enum Unit { item, pound, ounce, dozen };
public static void Main()
{
var item = new Vegetable("eggplant");
var date = DateTime.Now;
var price = 1.99m;
var unit = Unit.item;
//On 2023/5/23 16:58:26, the price of eggplant was 1.99 per item.
Console.WriteLine($"On {date}, the price of {item} was {price} per {unit}.");
}
}
//字符替换
string message = "hello";
Console.WriteLine(message);
message = message.Replace("hello", "bye");
Console.WriteLine(message);
//搜索文本
string message = "You say goodbye, and I say hello";
Console.WriteLine(message.Contains("goodbye"));
Console.WriteLine(message.Contains("greetings"));
//得到:
//false
//true
//或者StartWith/EndWith:
string message = "you say goodbye and I say hello";
Console.WriteLine(message.StartsWith("you"));
Console.WriteLine(message.EndsWith("hello"));
//构造函数
using System;
namespace MyApp
{
public class Test
{
//构造函数,名称必须与类的名称相同,所以接下来那句 public Test()必须写。
public Test()
{
System.Diagnostics.Debug.WriteLine("构造函数被调用");
}
//析构函数,用来销毁不需要的类实例,以~开头,没有返回值
~Test()
{
System.Diagnostics.Debug.WriteLine("析构函数被调用");
}
}
class Program //默认这部分必须写
{
static void Main(string[] args)
{
Test t = new Test();
}
}
}
public static void main(String[] args) 是什么意思
这是java程序的入口地址,java虚拟机运行程序的时候首先找的就是main方法,然后执行main里面的语句。跟C语言里面的main()函数的作用是一样的.只有有了main()方法的java程序才能够被java虚拟机欲行,可理解为规定的格式。
对于里面的参数及修饰符:
public:表示的这个程序的访问权限,表示的是任何的场合可以被引用,这样java虚拟机就可以找到main()方法,从而来运行javac程序
static:表明方法是静态的,不依赖类的对象的,是属于类的,在类加载的时候main()方法也随着加载到内存中去
void:main()方法是不需要返回值的。
viod的意思是不需要回传。如果你需要回传一个int类型的值,则改写成static int即可。
main:约定俗成,规定的
String[] args:从控制台接收参数
在main()方法里面写代码。写入console.writeline("hello,world");
但是发现闪了一下就没了,这时候多输入一行console.readline();则会停在相应界面。因为这个 console.readline函数意思是读取界面输入值。
C# 命名空间(Namespace
)
定义命名空间
命名空间的定义是以关键字 namespace 开始,后跟命名空间的名称,如下所示:
namespace namespace_name
{
// 代码声明
}
为了调用支持命名空间版本的函数或变量,会把命名空间的名称置于前面,如下所示:
namespace_name.item_name;
下面的程序演示了命名空间的用法:
using System;
namespace first_space
{
class namespace_cl
{
public void func()
{
Console.WriteLine("Inside first_space");
}
}
}
namespace second_space
{
class namespace_cl
{
public void func()
{
Console.WriteLine("Inside second_space");
}
}
}
class TestClass
{
static void Main(string[] args)
{
first_space.namespace_cl fc = new first_space.namespace_cl();
second_space.namespace_cl sc = new second_space.namespace_cl();
fc.func();
sc.func();
Console.ReadKey();
}
}
当上面的代码被编译和执行时,它会产生下列结果:
Inside first_space
Inside second_space
using 关键字表明程序使用的是给定命名空间中的名称。例如,我们在程序中使用 System 命名空间,其中定义了类 Console。我们可以只写:
Console.WriteLine ("Hello there");
我们可以写完全限定名称,如下:
System.Console.WriteLine("Hello there");
您也可以使用 using 命名空间指令,这样在使用的时候就不用在前面加上命名空间名称。该指令告诉编译器随后的代码使用了指定命名空间中的名称。下面的代码演示了命名空间的应用。
让我们使用 using 指定重写上面的实例:
using System;
using first_space;
using second_space;
namespace first_space
{
class abc
{
public void func()
{
Console.WriteLine("Inside first_space");
}
}
}
namespace second_space
{
class efg
{
public void func()
{
Console.WriteLine("Inside second_space");
}
}
}
class TestClass
{
static void Main(string[] args)
{
abc fc = new abc();
efg sc = new efg();
fc.func();
sc.func();
Console.ReadKey();
}
}
当上面的代码被编译和执行时,它会产生下列结果:
Inside first_space
Inside second_space
using static 指令:指定无需指定类型名称即可访问其静态成员的类型
using static System.Math;var = PI; // 直接使用System.Math.PI
起别名
using Project = PC.MyCompany.Project;
将实例与代码绑定
using (Font font3 = new Font("Arial", 10.0f),
font4 = new Font("Arial", 10.0f))
{
// Use font3 and font4.
}
代码段结束时,自动调用font3和font4的Dispose方法,释放实例
命名空间可以被嵌套,即您可以在一个命名空间内定义另一个命名空间,您可以使用点(.)运算符访问嵌套的命名空间的成员
using System;
using SomeNameSpace;
using SomeNameSpace.Nested;
namespace SomeNameSpace
{
public class MyClass
{
static void Main()
{
Console.WriteLine("In SomeNameSpace");
Nested.NestedNameSpaceClass.SayHello();
}
}
// 内嵌命名空间
namespace Nested
{
public class NestedNameSpaceClass
{
public static void SayHello()
{
Console.WriteLine("In Nested");
}
}
}
}
命名空间静态:
using static xxx 就可以引用静态的类。比如console就是静态的类
一般写成using static System.Console;
如果只写了using System,那么在引用console的时候就需要把类名字写上,比如
using System
……
Console.WriteLine()
或写成
using static System.Console;
……
WriteLine(); //直接使用console中的静态writeline类
Read(); //直接使用console中的静态read类
Main
方法
Main
方法必须定义为static
Main
必须首字母大写
返回值必须是void
或int
类型,不能有其他
命令行参数可选(一般不写)=>
一般写成以下形式:static void Main(string[] arg)
这句就是命令行参数。
Main()
默认为c#的切入点,也就是程序开始运行的地方。默认格式为以下代码。注意只能无需返回(void)或返回0(int),只有这两种类型,否则会报错。
int
类型
如果用static int Main() {}
则必须有返回值,否则提示:
CS0161 C# '': not all code paths return a value
这时改成:
static int Main()
{
//输入内容
Console.WriteLine("hello,world");
Console.ReadLine();
return 0; //加入这一行,程序就可行了。
}
常见错误
1.CS5001 C#
程序不包含适合于入口点的静态 “Main” 方法
原因:没写Main(),或者写成小写main(),或者不是static类型。
解决办法:检查Main()书写是否正确。
2.CS0161 C# '': not all code paths return a value
并非所有的代码路径都返回值
解决办法:当需要用int类型时,需加入return 整数来返回。
3.CS0017 C#
程序定义了多个入口点。使用 /main (指定包含入口点的类型)进行编译指定Main()入口
原因:定义了多个Main()程序的入口比如在下图,两个namespace
都有Main()
。就会发生错误。
解决办法:打开该解决方法的属性,在应用程序=>启动对象里面设置相应的入口命名空间即可。
常用代码规则
-
尽量使用接口编程 - 关键语句一定要注释
-
局部变量随用随声明 - 尽量少用
go to
语句 -
如果参数多,建议用结构 - 避免对大段代码使用
try...catch
-
同一个文件夹中避免编写多个类 - 字符串多变时,用
stringBuilder
-
if
语句快中使用“{}” - switch
语句中一定编写default
命名规则
项目名、命名空间名(一般与项目名相同,自动生成)、接口名
类名(如class User,很直观知道是与用户有关的)、方法名、成员变量名(一般加前缀下划线)
引用类的层级关系
.NET Framework 4.6 and 4.5 => .NET Framework 類別庫 => System => console 类别=> console方法/console属性/ console 事件
console 是c#中设定好的一个类,并且是静态的,所以在引用console的时候需要在一开始写:using System.Console
,或者需要在被引用的时候写System.Console.WriteLine();
数据类型
货币(“C”)格式说明符
十进制(“D”)格式说明符
指数(“E”)格式说明符
定点(“F”)格式说明符
常规(“G”)格式说明符
数字(“N”)格式说明符
百分比(“P”)格式说明符
往返过程(“R”)格式说明符
十六进制(“X”)格式说明符
编译时常量const
需要一开始就赋值,如果是运行时常量readonly
,则可以在运行时候在g构造函数中再赋值。
//常量一般常量名都大写
using System
public class Program
{
const ABC = 900; //设定名叫abc的常量,值是900。常量类型一般用const表示
static void Main(string[] agrs)
{
Console.WriteLine("常量abc的值是:{0}", abc); //这里{0}必须写,否则出错
}
}
类体 => 成员变量
- 实例变量
string x = "hello";
实例变量只属于某个对象实例,所以调用时候需要先创建实例。 - 静态变量
static string x = "hello";
静态变量是属于一整个class 类的
两者的区别:如果输入了static
变量以后,则我们可以在该类的 static void main() 中直接调用
//局部变量如果在外部用?没其他办法,最简单的就是直接加一个static
class Program()
{
static string X = "hello";
static void Main()
{
Console.WriteLine(x);
}
}
//如果是用了实例变量,那么我们必须先用 Program 创建对象,否则会提示:
//CS0120 C# An object reference is required for the non-static field, method, or property 对象引用于非静态的字段,方法或属性“Program.x”是必须的
class Program()
{
string X = "hello";
static void Main()
{
Program p = new Program();
Console.WriteLine(p.x); //注意这里括号里面写的是对象名p,而不再是变量名
}
}
//可定义时直接赋值,也可以借助Program()来执行。不能定义在具体对方法中,只能定义在类里面,或者是在构造函数Program里面初始化,其余不行。是一行运行的,所以有顺序
class Program()
{
readonly int Price;
Program()
{
Price = 365;
}
static void Main()
{
……;
}
}
注意,如果是readonly时,那么代码是一行行读取的。
这时候如果先写了price3=price4*\2,再写Price4 = 55,那么price3的值只能是0。
运算符
关系运算符
==, !=, <, >, <=, >=
等。但关系运算符不能连用。
比如:
console.writeline(a<b<c);
提示输出错误。因为系统是从左到右判断。先执行了a<b以后得到到是bool
类型的值,再执行bool<c
的判断,就会发生错误。
这时候可以用a<b && b<c;
即可
位运算符
作用的对象是二进制数。
比如:&、|、^、~
- 位与运算
&
,两个数都是1,才返回1。如1 & 0
,返回0。 - 位或运算
|
,只要有一个是1,就返回1。如1 | 0
,返回1。 - 位异或运算
^
,两个都是0,或者两个都是1,则返回0,否则返回1。如11 ^ 10
,返回01。 - 位取反运算
~
,把0变成1,把1变成0即可。
移位运算
<<
左移位
数字转换成二进制以后,最左边到数(高位数)被移出去舍弃,右边的数补充0。也就是等于原来的数✖️2的n次幂。比如移2位就是原来数✖️2²。
>>
右移位
左边被填充进来。需要注意的是,如果是负数,那么填充的是1,如果是正数,那么填充的是0,相当于÷2的 n 次幂。
条件运算(三目运算)
static void Main()
{
int num = 50;
string result = num>40?"is true":"is false";
console.writeline(result);
console.readline();
}
Get和Set
一般用get获取属性值,用set重置属性值。
class Student
{
//姓名
string name;
public string Name
{
get { return this.name;}
set { this.name = value;}
}
//年龄
string age;
public string Age
{
get { return this.age;}
set { this.age = value;}
}
//地址
string address;
public string Address
{
get { return this.address;}
set { this.address = value;}
}
}
//属性封装
class Student
{
//姓名
string name;
public string Name
{
get { return this.name; }
set
{
if ( value == "")
{
throw new ArgumentException("姓名字段不能为空");
this.name = value;
}
}
}
//年龄
int age;
public int Age
{
get { return this.age; }
set
{
if (value < 1 || value > 100)
{
throw new ArgumentException("年龄超出范围");
this.age = value;
}
}
}
}
属性也可以直接通过对象名后面加点 . 来调用或赋值
Student stu = new Student;
stu.Age = -2;
如果属性不需要特殊处理,可以直接
public string Name {get; set;}
对于只读属性,只要在声明时自动忽略就可以:
public string ProductNo{get;}
判断语句
switch (str)
{
//witch的每个case语句后面都必须有break。
case "IBC":
case"ibc":
console.writeline("中国建设银行");
break
}
//省略第一个赋值,但需要初始化值。分号不能省略
int i=1;
for(; i<=100;i++){}
// 死循环
for(;;)
{
console.writeline("please enter your name:");
console.readline();
}
//在for语句中,表达式1与表达式3都可以用逗号连接多个条件,但表达式2不行,只能用&& 来连接
for (i = 1; i<=100 && i>0; i++)
{
sum +=i;
}
例子打印9×9乘法表:
int i,j;
for(i=1; i<10; i++)
{
for(j=1; j<=i; j++)
{
console.write("{0}×{1} = {2}", i, j, i*j); //这里{0}是占位符的意思。
console.write(" "); //这里的意思是保证每个结果之间有间隙,不会挤一起
}
console.writeline(); //这里意思是一行完了以后就换行
}
console.readline();
continue 跳过本次循环,进行下一次
遇到break以后,直接跳过while括号内的语句,不再执行。若遇到continue,则继续执行新一次while语句循环,直到条件满足,再继续。
break 需用在switch语句中,continue只能用在for循环语句中与if配套使用,不能单独用在if语句中。
数组
int[] arr = new int[3]; // 只定义数组的长度,不定义具体内容,是可行的
常见错误
int arr[] = new int[3];
错在[]位置写错,应该是int[] arrint[] arr = new int[3] {1,2 }
错在如果定义了数组长度是3,但初始化的时候只有2个数,那么会提示错误。int[] arr = new string[3]
错在左边定义了int类型,右边又定义了string类型,相冲突。
二维数组表达
int [ , ] 或string [][]
//般用第一种方法
int[,] arr = new int [2, ]
//因为第二种方法也叫不规则数组,没法指定列数。否则代码错。
//CS0178 C# Invalid rank specifier: expected ',' or ']' 无效的秩说明符:应为“,”或“]”
int[, ] arr = new int[2, ]; //不指定列数
a[0] = new int[2]; //第0行有2列
a[1] = new int[4]; //第1行有4列
//初始化二维数组
int[ , ] arr = {{12,12}, {13,13}, {14,14}}; //这里右边不能再写new,否则错误
int[ , ] arr = new int[] {{12,12}, {13,13}, {14,14}}; //这样才对
正序排序
Array.Sort(arr);
反转排序
Array.Reverse;
倒序排序
Array.Sort(arr);
Array.Reverse;
//foreach 遍历数组来输出
//但这么执行以后,显示的就不是二维数组而是一维数组
static void Main(string[] args)
{
int[,] arr = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int i, j;
Console.WriteLine("原始数组");
foreach (int a in arr) // 这里的a只是我们随意定义的一个代词用来表示arr中的元素,也可以是其他名字
{
Console.Write(a + " ");
}
Console.WriteLine("arr's length: "+arr.Length);
Console.ReadLine();
}
字符
public int IndexOf(string value) //获取第一次出现的索引
string str = "we are the world";
int index = str.indexOf("e");
public int IndexOf(stirng value, int startindex); //从指定位置往后查
string str = "we are the world";
int index = str.IndexOf("e", 3);
public int IndexOf(string value, int startindex, int count) //从指定位置往后检查几个字符
string str = "we are the world";
int index = str.IndexOf("e", 3, 5);
//如果不存在该数字,则返回的位置值为-1。
//判断字符串结尾-后缀名
//会输出true,则表示是以这个后缀结尾,如果不是,则返回false。
string str = "Program.cs";
bool b = str.EndsWith(".cs");
console.writeline(b);
//如果不想区分大小写:
public bool EndsWith(string value, bool ignoreCase, CultureInfo culture)
//endswith后面可以跟三个参数,第一个参数就是value值,第二个参数就是是否忽略大小写(true 为忽略,false为不忽略),第三个参数一般null就行:
string str = "Program.cs";
bool b2 = str.EndsWith(".cs", true, null);
//判断字符串开头StartWith
string str = "Program";
bool b3 = str.EndsWith("Pro");
//compare方法——返回int值
//需要static,因为是直接调用string 下面的compare方法
//如果返回为0,则表示m1==m2,如果返回1,则表示m1>m2,返回-1则表示m1<m2。
string m1 = "mj";
string m2 = "mjk";
console.writeline(string.compare(m1, m2)); //此处直接写string.compare,直接调用string字符串这个类 下面的compare 方法。
//忽略大小写
console.writeline(string.compare(m1, m2, true));
//compareTo方法——返回int值
//不需要static,因为compareTo为对象比较。
console.writeline(m1.CompareTo(m2)); //直接用对象名后面加点就可以调用方法
//✨Equals方法——返回bool值,一般开发中较常用
//大小写
public string TpUpper();
public string ToLower();
string str = "Good good study, day day Up.";
string sUp = str.ToUpper();
string sLo = str.ToLower();
数值格式显示
console.writeline(string.Format("金额显示: {0:c}", 368)); //注意冒号的位置,0表示占位符,占位符后面接的才是格式化的类型。占位符{0}后面要冒号,然后再写入要格式化的代码,比如 c金额格式。c表示保留两位小数,{0:c0}则表示整数。
console.writeline(string.Format("pi的值: {0:F2}", Math.PI)); //输出pi 的值
//截取字符串
string fileName = "Program.cs";
string s1 = fileName.Substring(0, fileName.indexOf("."));//0的意思是从第0号位置开始截取,一直到出现“.”的时候结束。
console.writeline(s1);
//如果要从"."开始,则可以这么写:
string fileName = "Program.cs";
string s2 = fileName.Substring(fileName.indexOf("."));
console.writeline(s2);
console.readline();
//分割字符串
//string str = "abc, def, ghi";
string[] a1 = str.split(new char[ ] {'.'}); //意思是,用字符'.'来进行分割。如果有其他符号,也可以继续在 char 里面写。
console.writeline("please enter your num:");
string str = console.readline(); //让用户自行输入一个带符号“.”的数据
string [] a1 = strName.split(new char []{'.'}); //通过'.'这个字符,来对用户输入的数进行分割。注意这里用的是char ,所以要单引号。
//例子:
foreach(string a in a1)
{
console.write(a + " ");//a 只是我们随意定义的一个变量名,用来表示字符串数组内的值。用foreach方法遍历数组,再输出
}
console.readline();
//指定分割次数:
string str = "abc, def, ghi";
string a2 = str.splite(new char[ ] {"."}, 2); //会变成下图右边的形式。
//删除空格
string.Trim()
string str = " abc ";
console.writeline(str.Trim());
//删除指定字符
string str = "777777abc@@@";
char[] ch = {'7', '@'};
console.writeline(str.Trim(ch));
//字符串替换,替换单个字符
string str = "77777abc7777";
string rp = str.Replace('7', '8');
console.writeline(rp);
//替换多个字符
string str = "77777abc777";
string rp2 = str.Replace("ab", "de");
console.writeline(rp2);
//如果用了stringbuilder,就不能像上述一样str += "def"了。而是要用相关的方法来定义
stringBuilder str = new stringBuilder ("hello");
console.writeline(str.Append(" amy"));
console.readline();
对象、类、访问权限、静态动态函数
//枚举
public enum MM
{
cs = 1, //用逗号,不是分号
c = 2,
java = 3 //最后一个不用加分号
}
public enum MM
{
cs = 1, //用逗号隔开
c = 2,
java = 3
}
static void Main()
{c
console.writeline((int)MM.c);
}
ng.Trim()
string str = " abc ";
console.writeline(str.Trim());
//删除指定字符
string str = “777777abc@@@”;
char[] ch = {‘7’, ‘@’};
console.writeline(str.Trim(ch));
//字符串替换,替换单个字符
string str = “77777abc7777”;
string rp = str.Replace(‘7’, ‘8’);
console.writeline(rp);
//替换多个字符
string str = “77777abc777”;
string rp2 = str.Replace(“ab”, “de”);
console.writeline(rp2);
[外链图片转存中...(img-za6BNnU3-1687749710067)]
```c#
//如果用了stringbuilder,就不能像上述一样str += "def"了。而是要用相关的方法来定义
stringBuilder str = new stringBuilder ("hello");
console.writeline(str.Append(" amy"));
console.readline();
对象、类、访问权限、静态动态函数
//枚举
public enum MM
{
cs = 1, //用逗号,不是分号
c = 2,
java = 3 //最后一个不用加分号
}
public enum MM
{
cs = 1, //用逗号隔开
c = 2,
java = 3
}
static void Main()
{c
console.writeline((int)MM.c);
}