目录
1 字段与属性的初始化方式汇总
C#中类可以包含三种成员:
字段(Field)
方法(Method)
属性(Property)
其中,属性为字段的进一步封装。
1.1 对象初始化方式
假设我们定义一个类 Student
public class Student
{
public string name;
public int age;
}
我们可以通过采用以下方式直接给对象字段(或属性)赋初值:
Student objStudent = new Student();
objStudent.age = 24;
objStudent.name = "Devin";
当遇到一个类定义了多个字段或属性时,可以通过类的构造函数来赋初值:
public class Student
{
public string name;
public int age;
public Student(string _name, int _age) // 类的构造函数
{
this.name = _name;
this.age = _age;
}
}
然后,只需要一句代码即可达到创建对象并初始化其字段的目的:
Student objStudent = new Student("Devin",24);
当需要在不同场合下可能需要初始化部分的字段时,可以使用"对象初始化器"
Student objStudent = new Student { name = "Kevin", age = 23 };
// 或
Student objStudent = new Student { age = 23 };
1.2 自动实现的属性
“自动实现的属性”这一语法特性其实是对标准属性实现形式的一种简写,如下:
public class Student
{
public int Number { get; set; }
}
C#编译器编译上述代码是,会生成一个私有字段,并自动创建相应的get/set访问器方法,将“自动实现的属性”转换为属性的标准实现方式。所以,上述代码完全等同于以下代码:
public class Student
{
private int _Number = 0;
public int Number
{
get { return _Number; } // “读”访问器方法
set { _Number = value; } // “写”访问器方法
}
}
提示:
如果想定义只读的属性,可以让set访问器为private:
public class Student
{
public int Number { get; private set; }
}
2 让一个方法返回多个结果
2.1 在方法体外定义变量保存结果
可以将方法要返回的结果保存到类的字段或属性中,在方法体内存取这些字段:
class MyClass
{
public int quotient; // 商
public int remainder; // 余数
public void Divide(int x, int y)
{
quotient = x / y;
remainder = x % y;
}
}
使用这种编程方式,一个方法可以“返回”任意多个结果,但需要特别注意,在多线程环境下如果多个线程需要同时调用此方法,则必须锁定整个对象以保证数据的正确存取。
2.2 使用“输出型”和“引用型”参数
C#支持定义两种特殊类型的参数:“输出型”和“引用型”。这两种方式都允许方法去修改“方法调用者”传送给它的实参数值,本质上是通过地址直接修改“外部”的变量值。
“输出型”,out关键字:
class MyClass
{
public void Divide(int x, int y, out int _quotient, out int _remainder)
{
_quotient = x / y;
_remainder = x % y;
}
}
调用拥有输出型参数的方法,实参前也要加out关键字:
int quotient;
int remainder;
Divide(10, 3, out quotient, out remainder);
“引用型”,ref关键字:
int quotient = 0; // 必须要显示初始化
int remainder = 0;
Divide(10, 3, ref quotient, ref remainder);
注:方法的引用型参数指的是“通过引用(即地址)传递参数”,注意不要与“引用类型”概念混淆,方法参数无论是值类型还是引用类型,都可通过ref进行修饰。
总结:
out与ref 的区别:
out只输出,不输入(不需要初始化);
ref输入的形参必须要初始化,即必须要传递值。
2.3 让方法返回一个对象或结构变量
可将返回的值封装到一个对象(或结构体)中,将其作为方法的返回值。
public struct DivideResult
{
public int quotient; // 商
public int remainder; // 余数
}
返回定义的结构体,就可得到所需的两个计算结果:
static DivideResult Divide(int x, int y)
{
DivideResult result;
result.quotient = x / y; // 将商保存到result变量中
result.remainder = x % y; // 将余数保存到result变量中
return result;
}
2.4 使用Tuple对象作为方法的形参或返回值
可以调用Tuple.Create静态方法或使用new关键字直接创建一个Tuple对象,.NET基类库中定义了拥有1~7个泛型参数的泛型Tuple。
static Tuple<int,int> Divide(int x, int y)
{
return new Tuple<int, int>(x / y, x % y);
}
使用Tuple对象的Item1和Item2属性读取值:
Tuple<int, int> result = Divide(10, 3);
Console.WriteLine("{0},{1}", result.Item1, result.Item2);
注意,Item属性为只读的 :
public T1 Item1 { get; }
3 命名参数与可选参数
3.1 自定义的命名参数
“命名参数”即通过在调用方法时,直接根据参数名字传送实参,不用像原来一样需要依据方法定义时的参数顺序传送。
例如,假设有以下方法:
static void SomeMethod(int x1, int x2, int y1, int y2)
{
// TODO
}
则可以这样调用这个方法:
private void TestFunc()
{
SomeMethod(x1: 100, y1: 300, x2: 50, y2: 200); // 命名方式,次序无关紧要
}
3.2 定义了默认值的可选参数
所谓“可选参数”,是指给方法的特定参数指定默认值,在调用方法时,可以省略掉这些参数。
static void Test(int required,string optionalString = "Default Value")
{
// TODO
}
则以下两种调用方法都是可行的:
Test(100); // optionalString参数拥有默认值“Default Value”
Test(100, "New Value"); // optionalString参数值为“New Value”
4 分部类
在定义一个类时加上partial关键字,此类即成为分部类。
分部类主要用于隔离来源不同、功能不同或类型不同的源代码。
以Windows Forms窗体为例,主窗体文件“Form1.cs” 与 “Form1.Designer.cs”中,两个文件中“Form1”类名前都添加了一个“partial”关键字。