目录
属性和方法是C#程序中的两个重要组成部分,其中,属性提供灵活的机制来读取、编写或计算私有字段的值,而方法则以一部分代码构成代码块的形式存在,用来实现特定的功能。
一、属性
属性提供功能强大的方法以将声明信息与C#代码(类型、方法、属性等)相关联,一旦属性与程序实体关联,即可使用名为反射的技术对属性进行查询。
属性是一种用于访问对象或类的特性的成员,它可以表示字体的大小、窗体的标题和客户的名称等内容。
属性有访问器,这些访问器指定在它们的值被读取或写入时需要执行的语句。因此属性提供了一种机制,它把读取和写入对象的某些特性与一些操作关联起来。可以像使用公共数据成员一样使用属性,但实际上它们是称为“访问器”的一种特殊方法,这使得数据在被轻松访问的同时,仍能提供方法的安全性和灵活性。
属性不能作为ref参数或out参数传递。
1、属性具有以下特点:
☑ 属性可向程序中添加元数据。元数据是嵌入程序中的信息,如编译器指令或数据描述。
☑ 程序可以使用反射检查自己的元数据。
☑ 通常使用属性与COM交互。
2、属性的两种存在形式:
一种是在公共语言运行库的基类库中定义的属性;
[System.Serializable] //Serialzable为.NET Framework类库中定义的属性
public class MyClass
{}
另一种是自己创建、可以向代码中添加附加信息的自定义属性。指定属性的访问级别,后面是属性的类型,接下来是属性的名称,然后是声明get访问器和(或)set访问器的代码模块,其他语法格式:
访问修饰符 数据类型 属性名 //自定义属性在类中是通过以下方式声明的
{
get
{
return 变量名;
}
set
{
变量名=value;
}
}
访问修饰符用来确定属性的可用范围,常用的几个访问修饰符。
☑ public:不限制对该属性的访问。
☑ protected:只能从其所在类和所在类的子类(派生类)进行访问。
☑ internal:只有其所在类才能访问。
☑ private:私有访问修饰符,只能在其声明类中使用。
get访问器与方法体相似,它必须返回属性类型的值;而set访问器类似于返回类型为void的方法,它使用称为value的隐式参数,此参数的类型是属性的类型。
3、属性的调用
程序中调用属性的语法格式:对象名 属性名;
☑如果要在其他类中调用自定义属性,必须将自定义属性的访问级别设置为public。
☑如果属性为只读属性,不能在调用时为其赋值,否则产生异常
/// <summary>
/// 属性
/// 自定义两个属性,用来表示用户编号和姓名
/// </summary>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test8_1
{
class MyClass
{
private string id = ""; //定义一个string类型的变量,用来记录用户编号
/// <summary>
///定义用户编号属性,该属性为可读可写属性
/// </summary>
public string ID
{
get
{
return id;
}
set
{
id = value;
}
}
private string name = ""; //定义一个string类型的变量,用来记录用户姓名
/// <summary>
///定义用户姓名属性,该属性为可读可写属性
/// </summary>
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
class Program
{
static void Main(string[] args)
{
if (args is null) //解除IDE0060
{
throw new ArgumentNullException(nameof(args));
}
MyClass myclass = new() //实例化MyClass类对象
{
//myclass.ID = "BH001"; //IDE0017 可以简化对象初始化
//myclass.Name = "TM1";
ID = "BH001", //为用户编号属性赋值
Name = "TM1" //为用户姓名属性赋值
};
Console.WriteLine(myclass.ID + " " + myclass.Name); //输出用户编号和用户姓名
myclass.ID = "BH002"; //重新为用户编号属性赋值
myclass.Name = "TM2"; //重新为用户姓名属性赋值
Console.WriteLine(myclass.ID + " " + myclass.Name); //再次输出用户编号和用户姓名
Console.Read();
}
}
}
/*运行结果:
BH001 TM1
BH002 TM2 */
二、方法
方法是一种用于实现可以由对象或类执行的计算或操作的成员。类的方法主要是和类相关联的动作,它是类的外部界面。对于那些私有的字段来说,外部界面实现对它们的操作一般只能通过方法来实现。
1、方法的声明
方法是包含一系列语句的代码块,在C#中,每个执行指令都是在方法的上下文中完成的。
方法在类或结构中声明,声明时需要指定访问级别、返回值、方法名称及方法参数,方法参数放在括号中,并用逗号隔开。括号中没有内容表示声明的方法没有参数。
方法声明可以包含一组特性和private、public、protected、internal这4个访问修饰符的任何一个有效组合,还可以包含new、static、virtual、override、sealed、abstract以及extern等修饰符。
如果以下所有条件都为真,则表明所声明的方法具有一个有效的修饰符组合。
☑ 该声明包含一个有效的访问修饰符组合。
☑ 该声明中所包含的修饰符彼此各不相同。
☑ 该声明最多包含下列修饰符中的一个:static、virtual和override。
☑ 该声明最多包含下列修饰符中的一个:new和override。
☑ 如果该声明包含abstract修饰符,则该声明不包含下列任何修饰符:static、virtual、sealed或extern。
☑ 如果该声明包含private修饰符,则该声明不包含下列任何修饰符:virtual、override或abstract。
☑ 如果该声明包含sealed修饰符,则该声明还包含override修饰符。
方法声明的返回类型指定了由该方法计算和返回值的类型,如果该方法并不返回值,则其返回类型为void。
一个方法的名称和形参列表定义了该方法的签名,具体地讲,一个方法的签名由它的名称以及它的形参的个数、修饰符和类型组成。返回类型不是方法签名的组成部分,形参的名称也不是方法签名的组成部分。
一个方法的返回类型和它的形参列表中所引用的各个类型必须至少具有与该方法本身相同的可访问性。
对于abstract和extern方法,方法主体只包含一个分号。对于所有其他方法,方法主体由一个块组成,该块指定了在调用方法时要执行的语句。
方法的名称必须与在同一个类中声明的所有其他非方法成员的名称都不相同。此外,一个方法的签名必须与在同一个类中声明的所有其他方法的签名都不相同,并且在同一类中声明的两个方法的签名不能只有ref和out不同。
2、方法的参数类型
调用方法时可以给该方法传递一个或多个值,传给方法的值叫作实参,在方法内部,接收实参的变量叫作形参,形参在紧跟着方法名的括号中声明,形参的声明语法与变量的声明语法一样。形参只在括号内部有效。声明方法参数时,可以通过关键字params、ref和out实现。
(1)params参数
params参数用来指定在参数数目可变时采用的方法参数,params参数必须是一维数组。
//params参数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace paramsExam
{
class Program
{
static void UseParams(params string[] list) //用于遍历的方法,list形参
{
for (int i = 0; i < list.Length; i++)
{
Console.WriteLine(list[i]);
}
}
static void Main()
{
string[] strName = new string[5] { "我", "是", "中", "国", "人" };
UseParams(strName); //调用方法,遍历
Console.Read();
}
}
}
/*运行结果:
我
是
中
国
人
*/
(2)ref参数
ref参数使方法参数按引用传递,其效果是:当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。如果要使用ref参数,则方法声明和调用方法都必须显式使用ref关键字。
//ref参数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace refExam
{
class Program
{
public static void Method(ref int i)
{
i = 44;
}
public static void Main()
{
int val = 0;
Method(ref val); //使用ref关键字,方法对参数的改变被传递回调用
Console.WriteLine(val);
Console.Read();
}
}
}
/*运行结果:
44 */
(3)out参数
out关键字用来定义输出参数,它会导致参数通过引用来传递,这与ref关键字类似,不同之处在于ref要求变量必须在传递之前进行初始化,而使用out关键字定义的参数,不用进行初始化即可使用。如果要使用out参数,则方法声明和调用方法都必须显式使用out关键字。
//out参数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace outExam
{
class Program
{
public static void Method(out int i)
{
i = 44;
}
public static void Main()
{
Method(out int value);
Console.WriteLine("输出参数:"+value);
Console.Read();
}
}
}
/*运行结果:
输出参数:44 */
3、方法的分类
方法分为静态方法和非静态方法,如果一个方法声明中含有static修饰符,则称该方法为静态方法;如果没有static修饰符,则称该方法为非静态方法。
(1)静态方法
静态方法不对特定实例进行操作,调用时,需要直接使用类名进行调用。
//static方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test8_5
{
class Program
{
public static int Add(int x, int y) //定义一个静态方法
{
return (x + y);
}
static void Main(string[] args)
{
if (args is null) //解除IDE0060
{
throw new ArgumentNullException(nameof(args));
}
Console.WriteLine("结果为:" + Program.Add(3, 5)); //使用类名调用静态方法
Console.WriteLine("结果为:" + Add(3, 5)); //直接调用静态方法
Console.Read();
}
}
}
/*运行结果:
结果为:8
结果为:8 */
(2)非静态方法
非静态方法是对类的某个给定的实例进行操作,调用时,需要使用类的实例(对象)进行调用。调用非静态方法时,也可以使用this关键字。
///<summary>
///非static方法
///定义一个非静态方法,会出现CA1822成员“Add”不访问实例数据,可标记为static;
///为了满足用实例对象调用方法的需求,采用了“无提示”抑制操作。
/// </summary>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test8_6
{
class Program
{
public int Add(int x, int y)
{
return (x + y);
}
static void Main(string[] args)
{
if (args is null) //解除IDE0060
{
throw new ArgumentNullException(nameof(args));
}
Program program = new();
///<summary>
///使用类对象调用定义的非静态方法
/// </summary>
Console.WriteLine("结果为:" + program.Add(3, 5));
Console.Read();
}
}
}
/*运行结果:
结果为:8 */
4、方法的重载
方法重载是指方法名相同,但参数的数据类型、个数或顺序不同的方法。只要类中有两个以上的同名方法,但是使用的参数类型、个数或顺序不同,调用时,编译器即可判断在哪种情况下调用哪种方法。
///<summary>
///方法的重载
///非静态方法,会出现CA1822成员“Add”不访问实例数据,可标记为static;
///为了满足用实例对象调用方法的需求,采用了“无提示”抑制操作。
/// </summary>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test8_7
{
class Program
{
public static int Add(int x, int y) //定义一个静态方法Add,返回值为int类型,有两个int类型的参数
{
return (x + y);
}
public double Add(int x, double y) //重新定义方法Add,它与第一个的返回值类型及参数类型不同
{
return (x + y);
}
public int Add(int x, int y, int z) //重新定义方法Add,它与第一个的参数个数不同
{
return (x + y + z);
}
static void Main(string[] args)
{
if (args is null) //解除IDE0060
{
throw new ArgumentNullException(nameof(args));
}
Program program = new(); //需要实例化类对象调用非静态方法
int x = 3;
int y = 5;
int z = 7;
double y2 = 5.5;
///<summary>
///根据传入的参数类型及参数个数的不同调用不同的Add重载方法
///第一个静态的方法,可以通过类名调用方法,也可以直接调用
///第二、三个是非静态的方法,必须通过类得实例化对象调用方法
/// </summary>
Console.WriteLine(x + "+" + y + "=" + Program.Add(x, y));
Console.WriteLine(x + "+" + y2 + "=" + program.Add(x, y2));
Console.WriteLine(x + "+" + y + "+" + z + "=" + program.Add(x, y, z));
Console.Read();
}
}
}
/*运行结果:
3+5=8
3+5.5=8.5
3+5+7=15
*/
5、Main()方法
Main()方法是程序的入口点,程序将在此处创建对象和调用其他方法,一个C#程序中只能有一个入口点,每新建一个项目,程序都会自动生成一个Main()方法。
默认的Main()方法:static void Main(string[] args)
Main()方法默认访问级别为private。
Main()方法是一个特别重要的方法,使用时需要注意以下几点:
☑ Main()方法是程序的入口点,程序控制在该方法中开始和结束。
☑ Main()方法在类或结构的内部声明,它必须为静态方法,而且不应该为公共方法。
☑ Main()方法可以具有void或int返回类型。
☑ 声明Main()方法时既可以使用参数,也可以不使用参数。
☑ 参数可以作为从零开始索引的命令行参数来读取。